var CrossDresser;
(function (CrossDresser) {
function deparam(params, coerce) {
var obj = {}, coerce_types = { 'true': !0, 'false': !1, 'null': null };
// Iterate over all name=value pairs.
$.each(params.replace(/\+/g, ' ').split('&'), function (j, v) {
var param = v.split('='), key = decodeURIComponent(param[0]), val, cur = obj, i = 0,
// If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it
// into its component parts.
keys = key.split(']['), keys_last = keys.length - 1;
// If the first keys part contains [ and the last ends with ], then []
// are correctly balanced.
if (/\[/.test(keys[0]) && /\]$/.test(keys[keys_last])) {
// Remove the trailing ] from the last keys part.
keys[keys_last] = keys[keys_last].replace(/\]$/, '');
// Split first keys part into two parts on the [ and add them back onto
// the beginning of the keys array.
keys = keys.shift().split('[').concat(keys);
keys_last = keys.length - 1;
}
else {
// Basic 'foo' style key.
keys_last = 0;
}
// Are we dealing with a name=value pair, or just a name?
if (param.length === 2) {
val = decodeURIComponent(param[1]);
// Coerce values.
if (coerce) {
val = val && !isNaN(val) ? +val : val === 'undefined' ? undefined : coerce_types[val] !== undefined ? coerce_types[val] : val; // string
}
if (keys_last) {
for (; i <= keys_last; i++) {
key = keys[i] === '' ? cur.length : keys[i];
var next_key = keys[i + 1];
cur = cur[key] = (i < keys_last) ? cur[key] || (next_key && isNaN(next_key) ? {} : []) : val;
}
}
else {
// Simple key, even simpler rules, since only scalars and shallow
// arrays are allowed.
if ($.isArray(obj[key])) {
// val is already an array, so push on the next value.
obj[key].push(val);
}
else if (obj[key] !== undefined) {
// val isn't an array, but since a second value has been specified,
// convert val into an array.
obj[key] = [obj[key], val];
}
else {
// val is a scalar.
obj[key] = val;
}
}
}
else if (key) {
// No value was defined, so set something meaningful.
obj[key] = coerce ? undefined : '';
}
});
return obj;
}
CrossDresser.deparam = deparam;
;
})(CrossDresser || (CrossDresser = {}));
;
///
///
var CrossDresser;
(function (CrossDresser) {
var Utils = (function () {
function Utils() {
}
Utils.parseUrl = function (url) {
var uri_part_names = ["source", "scheme", "authority", "host", "port", "path", "directory_path", "file_name", "query_string", "hash"];
var uri_parts = new RegExp("^(?:([^:/?#.]+):)?(?://)?(([^:/?#]*)(?::(\\d*))?)?((/(?:[^?#](?![^?#/]*\\.[^?#/.]+(?:[\\?#]|$)))*/?)?([^?#/]*))?(?:\\?([^#]*))?(?:#(.*))?").exec(url);
var uri = {};
for (var i = 0, size = uri_part_names.length; i < size; i++) {
uri[uri_part_names[i]] = (uri_parts[i]) ? uri_parts[i] : '';
}
uri.port = uri.port ? parseInt(uri.port) : 80;
var domain_parts = (/^(.*?)\.?([^\.]*\.\w+)$/).exec(uri.host);
if (domain_parts) {
uri.sub_domain = domain_parts[1];
uri.root_domain = domain_parts[2];
}
else {
uri.sub_domain = uri.root_domain = '';
}
if (uri.directory_path.length > 0) {
uri.directory_path = uri.directory_path.replace(/\/?$/, "/");
}
return uri;
};
Utils.parseQueryString = function (query_string) {
return CrossDresser.deparam(query_string);
};
Utils.createId = function () {
var _id = '';
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 1; i <= 20; i++) {
_id += possible.charAt(Math.floor(Math.random() * possible.length));
}
return _id;
};
//docReady(fn, context);
//the context argument is optional - if present, it will be passed
//as an argument to the callback
Utils.documentReady = function (callback, context) {
// if ready has already fired, then just schedule the callback
// to fire asynchronously, but right away
if (readyFired) {
setTimeout(function () {
callback(context);
}, 1);
return;
}
else {
// add the function and context to the list
readyList.push({ fn: callback, ctx: context });
}
// if document already ready to go, schedule the ready function to run
if (document.readyState === 'complete') {
setTimeout(ready, 1);
}
else if (!readyEventHandlersInstalled) {
// otherwise if we don't have event handlers installed, install them
if (document.addEventListener) {
// first choice is DOMContentLoaded event
document.addEventListener('DOMContentLoaded', ready, false);
// backup is window load event
window.addEventListener('load', ready, false);
}
else {
// must be IE
document.attachEvent('onreadystatechange', readyStateChange);
window.attachEvent('onload', ready);
}
readyEventHandlersInstalled = true;
}
};
return Utils;
})();
CrossDresser.Utils = Utils;
})(CrossDresser || (CrossDresser = {}));
// DOCUMENT READY HELPERS //////////////////////////////////////////////////////////////////////////////////////////////
var readyList = [];
var readyFired = false;
var readyEventHandlersInstalled = false;
// call this when the document is ready
// this function protects itself against being called more than once
function ready() {
if (!readyFired) {
// this must be set to true before we start calling callbacks
readyFired = true;
for (var i = 0; i < readyList.length; i++) {
// if a callback here happens to add new ready handlers,
// the docReady() function will see that it already fired
// and will schedule the callback to run right after
// this event loop finishes so all handlers will still execute
// in order and no new ones will be added to the readyList
// while we are processing the list
readyList[i].fn.call(window, readyList[i].ctx);
}
// allow any closures held by these functions to free
readyList = [];
}
}
function readyStateChange() {
if (document.readyState === "complete") {
ready();
}
}
///
///
var CrossDresser;
(function (CrossDresser) {
var INSTANCES = {};
CrossDresser.frames = INSTANCES;
var ChildFrame = (function () {
function ChildFrame(_id) {
this._id = _id;
if (!INSTANCES[_id]) {
throw new RangeError('No frame exists by the referenced _id');
}
this.instance = INSTANCES[_id];
this.url = this.instance.url;
this.height = this.instance.height;
this.is_native = this.instance.is_native;
}
ChildFrame.prototype.trigger = function (name) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var callbacks = this.callbacks(name);
for (var i = 0, size = callbacks.length; i < size; i++) {
callbacks[i].apply(this, args);
}
if (name == 'native-base-ready') {
this.loadContent();
}
else if (name == 'resize-frame') {
this.resize.apply(this, args);
}
};
ChildFrame.prototype.on = function (name, callback) {
this.callbacks(name).push(callback);
};
ChildFrame.prototype.callbacks = function (name) {
if (!this.instance.callbacks[name]) {
this.instance.callbacks[name] = [];
}
return this.instance.callbacks[name];
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ChildFrame.prototype.getElement = function () {
return this.element = this.element || $('iframe#' + this._id);
};
ChildFrame.prototype.loadContent = function () {
if (this.instance.content_prms) {
var frame = this;
this.instance.content_prms.then(function (html) {
frame.getElement()[0].contentWindow.CrossDresser.injectIntoPage(html);
});
}
};
ChildFrame.prototype.resize = function (new_height) {
new_height = (!new_height || parseInt(new_height) < 150) ? 150 : parseInt(new_height);
this.getElement().attr('height', new_height);
return null;
};
ChildFrame.create = function (settings) {
if (url) {
settings = { url: url };
}
var _id = CrossDresser.Utils.createId();
var url = settings.url.replace(/^\/\//, 'http://');
var attrs = settings.attrs || {};
var width = settings.width || 500;
var height = settings.height || 450;
var is_native = false;
if (settings.use_native_base) {
var goto_url = ((url.indexOf('?') > -1) ? url + '&' : url + '?') + $.param(attrs);
var content_prms = $.ajax({
url: goto_url,
dataType: 'jsonp',
jsonp: 'callback'
});
url = settings.use_native_base;
attrs = {};
is_native = true;
}
attrs.crss_drssr = _id + '::' + encodeURIComponent(CrossDresser.current.getConduitUrl());
if (goto_url) {
attrs.crss_drssr += '::' + encodeURIComponent(goto_url);
}
url = (url.indexOf('?') > -1) ? url + '&' : url + '?';
url += $.param(attrs);
INSTANCES[_id] = {
callbacks: {},
width: width,
height: height,
url: url,
is_native: is_native,
content_prms: content_prms
};
return new ChildFrame(_id);
};
ChildFrame.find = function (_id) {
if (INSTANCES[_id]) {
return new ChildFrame(_id);
}
};
ChildFrame.trigger = function (_id, name, args) {
var instance = this.find(_id);
if (!instance) {
throw ('could not find instance: ' + _id);
}
args = args.slice(0);
args.unshift(name);
instance.trigger.apply(instance, args);
};
return ChildFrame;
})();
CrossDresser.ChildFrame = ChildFrame;
})(CrossDresser || (CrossDresser = {}));
///
///
///
var CrossDresser;
(function (CrossDresser) {
var INSTANCES = {};
var DEFAULT_WIDTH = 500;
var DEFAULT_HEIGHT = 450;
var ChildPopup = (function () {
function ChildPopup(_id) {
this._id = _id;
if (!INSTANCES[_id]) {
throw new RangeError('No frame exists by the referenced _id');
}
this.instance = INSTANCES[_id];
this.name = this.instance.name;
this.url = this.instance.url;
this.width = this.instance.width;
this.height = this.instance.height;
}
ChildPopup.prototype.trigger = function (name) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var callbacks = this.callbacks(name);
for (var i = 0, size = callbacks.length; i < size; i++) {
callbacks[i].apply(this, args);
}
};
ChildPopup.prototype.on = function (name, callback) {
this.callbacks(name).push(callback);
};
ChildPopup.prototype.callbacks = function (name) {
if (!this.instance.callbacks[name]) {
this.instance.callbacks[name] = [];
}
return this.instance.callbacks[name];
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ChildPopup.prototype.open = function () {
setTimeout(function () {
var width = this.width, height = this.height, top = (window.screen.height / 2) - (height / 2), left = (window.screen.width / 2) - (width / 2);
top = top - (top * 0.2);
window.open(this.url, this.name, 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=1,width=' + width + ',height=' + height + ',top=' + top + ',left=' + left);
}.bind(this));
};
ChildPopup.create = function (settings) {
if (url) {
settings = { url: url };
}
var _id = CrossDresser.Utils.createId();
var attrs = settings.attrs || {};
var url = settings.url.replace(/^\/\//, 'http://');
var width = settings.width || DEFAULT_WIDTH;
var height = settings.height || DEFAULT_HEIGHT;
var name = settings.name || _id;
attrs.crss_drssr = _id + '::' + encodeURIComponent(CrossDresser.current.getConduitUrl());
url = (url.indexOf('?') > -1) ? url + '&' : url + '?';
url += $.param(attrs);
INSTANCES[_id] = {
url: url,
name: name,
width: width,
height: height,
callbacks: {}
};
return new ChildPopup(_id);
};
ChildPopup.find = function (_id) {
if (INSTANCES[_id]) {
return new ChildPopup(_id);
}
};
ChildPopup.trigger = function (_id, name, args) {
var instance = this.find(_id);
if (!instance) {
throw ('could not find instance: ' + _id);
}
args = args.slice(0);
args.unshift(name);
instance.trigger.apply(instance, args);
};
return ChildPopup;
})();
CrossDresser.ChildPopup = ChildPopup;
})(CrossDresser || (CrossDresser = {}));
var CrossDresser;
(function (CrossDresser) {
var resizer;
(function (resizer) {
var ELEMENTS_IN_HEIGHT = {};
var ELEMENT_HEIGHT_COUNT = 0;
var MIN_HEIGHT = 150;
var HEIGHT = 'auto';
var CURRENT_HEIGHT;
var CALLBACKS = {};
var AUTOSIZE_INTERVAL;
function run(args) {
if (!CrossDresser.current.is_frame)
return console.log('Notice: Skipping resize since we\'re not inside an iframe');
if (args == false)
return disableAutosize();
if (!args)
return calculateResize();
var has_changes = false;
var new_min_height = extractMinHeight(args);
if (new_min_height != MIN_HEIGHT) {
MIN_HEIGHT = new_min_height;
has_changes = true;
}
var new_height = extractHeight(args);
if (new_height != HEIGHT) {
if (new_height == 'auto')
enableAutosize();
if (!isNaN(new_height))
HEIGHT = new_height;
has_changes = true;
}
if (has_changes)
calculateResize();
}
resizer.run = run;
function addToHeightCalculations(element) {
var $element = $(element);
if (!$element.data('ffcore-element-id')) {
$element.data('ffcore-element-id', ELEMENT_HEIGHT_COUNT++);
}
ELEMENTS_IN_HEIGHT[$element.data('ffcore-element-id')] = $element;
}
resizer.addToHeightCalculations = addToHeightCalculations;
function removeFromHeightCalculations(element) {
delete ELEMENTS_IN_HEIGHT[$(element).data('ffcore-element-id')];
}
resizer.removeFromHeightCalculations = removeFromHeightCalculations;
function enableAutosize(interval) {
interval = interval || (CrossDresser.current.is_native ? 500 : 1000);
interval = interval < 100 ? 100 : interval;
if (AUTOSIZE_INTERVAL)
clearInterval(AUTOSIZE_INTERVAL);
HEIGHT = 'auto';
AUTOSIZE_INTERVAL = setInterval(function () {
calculateResize();
}, interval);
run();
}
resizer.enableAutosize = enableAutosize;
function disableAutosize() {
if (AUTOSIZE_INTERVAL) {
clearInterval(AUTOSIZE_INTERVAL);
}
}
resizer.disableAutosize = disableAutosize;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function calculateResize() {
var new_height = $('html').css('height', 'auto').height();
for (var k in ELEMENTS_IN_HEIGHT) {
var $elem = ELEMENTS_IN_HEIGHT[k];
if ($elem.css('position') != 'absolute')
continue;
var element_bottom = $elem.offset().top + $elem.outerHeight();
if (element_bottom > new_height)
new_height = element_bottom;
}
if (CURRENT_HEIGHT && new_height < MIN_HEIGHT)
new_height = MIN_HEIGHT;
var viewport_height = $(window).height();
if (CURRENT_HEIGHT && ((CURRENT_HEIGHT == viewport_height) || (CURRENT_HEIGHT < viewport_height + 10 && CURRENT_HEIGHT > viewport_height - 10))) {
if ((CURRENT_HEIGHT == new_height) || (CURRENT_HEIGHT < new_height + 10 && CURRENT_HEIGHT > new_height - 10))
return;
}
CURRENT_HEIGHT = (new_height < MIN_HEIGHT) ? MIN_HEIGHT : new_height;
CrossDresser.trigger('resize-frame', CURRENT_HEIGHT);
}
function extractMinHeight(args) {
var height;
if (args['min-height'])
height = args['min-height'];
if (args.minHeight)
height = args.minHeight;
if (args.min_height)
height = args.min_height;
height = parseInt(height);
return height == NaN ? 0 : height;
}
function extractHeight(args) {
var height;
if (args['height'])
height = args['height'];
height = parseInt(height);
return height == NaN ? 'auto' : height;
}
})(resizer = CrossDresser.resizer || (CrossDresser.resizer = {}));
})(CrossDresser || (CrossDresser = {}));
var CrossDresser;
(function (_CrossDresser) {
var conduit;
(function (conduit) {
function run(command, args) {
var promise;
if (_CrossDresser.current.is_native) {
promise = toParent(command, args);
}
else {
promise = toIframe(command, args);
}
return promise;
}
conduit.run = run;
function executeRemoteCommand(CrossDresser, child_type, child_id, command, args) {
var methods = {
frame: function () {
CrossDresser.ChildFrame.trigger(child_id, command, args);
},
popup: function () {
CrossDresser.ChildPopup.trigger(child_id, command, args);
}
};
methods[child_type]();
}
function toParent(command, args) {
var dfr = $.Deferred();
executeRemoteCommand(_CrossDresser.current.parent.CrossDresser, _CrossDresser.current.environment, _CrossDresser.current._id, command, args);
return dfr.resolve().promise();
}
function toIframe(command, args) {
var dfr = $.Deferred();
var attrs = {
_id: _CrossDresser.current._id,
command: command,
environment: _CrossDresser.current.environment,
args: args
};
var url = _CrossDresser.current.parent_conduit_url;
url = ((url.indexOf('?') > -1) ? url + '&' : url + '?') + $.param(attrs);
_CrossDresser.Utils.documentReady(function () {
var $iframe = $('ff-frame-controller');
if ($iframe)
$iframe.remove();
$iframe = $('');
$iframe.appendTo('body');
$iframe.load(function () {
dfr.resolve();
});
});
return dfr.promise();
}
function fromIframe(environment, url) {
var uri = _CrossDresser.Utils.parseUrl(url);
var params = _CrossDresser.Utils.parseQueryString(uri.query_string);
if (environment != params.environment) {
throw Error('environment does not match params.environment');
}
executeRemoteCommand(CrossDresser, environment, params._id, params.command, params.args);
}
conduit.fromIframe = fromIframe;
})(conduit = _CrossDresser.conduit || (_CrossDresser.conduit = {}));
})(CrossDresser || (CrossDresser = {}));
///
///
var CrossDresser;
(function (CrossDresser) {
var CONDUIT_PATH = '/cross-dresser.html';
var CALLBACKS = {};
var Current = (function () {
function Current() {
this.config = {
conduit_path: CONDUIT_PATH
};
this.raw_url = document.location.href;
this.raw_uri = CrossDresser.Utils.parseUrl(this.raw_url);
this.raw_params = CrossDresser.Utils.parseQueryString(this.raw_uri.query_string);
try {
if (window.opener || (window.top && window.top.opener)) {
this.environment = 'popup';
this.parent = window.opener || window.top.opener;
this.is_popup = true;
}
else if (window.top && window.top != window.self && document.referrer != this.raw_url.replace(document.location.hash, '')) {
this.environment = 'frame';
this.parent = window.top;
this.is_frame = true;
this.is_native = this.isNativeFrame();
}
else {
this.environment = 'toplevel';
this.parent = null;
}
}
catch (err) {
this.environment = 'toplevel';
}
this.initiateDocumentLoad();
if (this.is_frame) {
setTimeout(function () {
CrossDresser.resizer.enableAutosize();
});
}
}
Current.prototype.isNativeFrame = function () {
try {
var parent_host = CrossDresser.Utils.parseUrl(window.top.location.href).host;
var current_host = this.raw_uri.host;
return (parent_host == current_host) ? true : false;
}
catch (err) {
return false;
}
};
Current.prototype.getConduitUrl = function () {
return this.raw_uri.scheme + '://' + this.raw_uri.host + ([80, 443].indexOf(this.raw_uri.port) > -1 ? '' : ':' + this.raw_uri.port) + (this.config.conduit_path || CONDUIT_PATH);
};
Current.prototype.initiateDocumentLoad = function () {
var _this = this;
if (!this.raw_params.crss_drssr) {
return;
}
var array = this.raw_params.crss_drssr.split('::');
this._id = array[0];
this.parent_conduit_url = decodeURIComponent(array[1]);
if (array[2]) {
this.url_to_load = decodeURIComponent(array[2]);
}
if (this.url_to_load && !this.is_native) {
var url = this.url_to_load;
var crss_drssr = this._id + '::' + encodeURIComponent(this.parent_conduit_url);
window.location.href = ((url.indexOf('?') > -1) ? url + '&' : url + '?') + 'crss_drssr=' + crss_drssr;
}
else if (this.url_to_load && this.is_native) {
this.url = this.url_to_load;
this.uri = CrossDresser.Utils.parseUrl(this.url_to_load);
this.params = CrossDresser.Utils.parseQueryString(this.uri.query_string);
var bt = document.createElement('base');
bt.setAttribute('href', 'http://' + this.uri.host);
document.getElementsByTagName('head')[0].appendChild(bt);
setTimeout(function () {
_this.trigger('native-base-ready', _this.url_to_load);
});
}
else if (this.environment == 'toplevel') {
console.log('NOTICE: CrossDresser parent not found - running as toplevel');
}
else {
this.url = this.raw_url;
this.uri = this.raw_uri;
this.params = this.raw_params;
}
};
Current.prototype.trigger = function (name) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var promise = CrossDresser.conduit.run(name, args);
var callbacks = CALLBACKS[name] || [];
setTimeout(function () {
for (var i = 0, length = callbacks.length; i < length; i++) {
callbacks[i].apply(CrossDresser.current, args);
}
});
return promise;
};
Current.prototype.on = function (name, callback) {
CALLBACKS[name] = CALLBACKS[name] || [];
CALLBACKS[name].push(callback);
};
return Current;
})();
function config(config) {
CrossDresser.current.config.conduit_path = config.conduit_path || CrossDresser.current.config.conduit_path || CONDUIT_PATH;
}
CrossDresser.config = config;
function injectIntoPage(html) {
$(function () {
$('body').html(html);
});
}
CrossDresser.injectIntoPage = injectIntoPage;
CrossDresser.current = new Current();
})(CrossDresser || (CrossDresser = {}));
///
///
///
///
var CrossDresser;
(function (CrossDresser) {
function createFrame() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i - 0] = arguments[_i];
}
return CrossDresser.ChildFrame.create.apply(CrossDresser.ChildFrame, args);
}
CrossDresser.createFrame = createFrame;
function createPopup() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i - 0] = arguments[_i];
}
return CrossDresser.ChildPopup.create.apply(CrossDresser.ChildPopup, args);
}
CrossDresser.createPopup = createPopup;
function resize(args) {
CrossDresser.resizer.run(args);
}
CrossDresser.resize = resize;
CrossDresser.trigger = CrossDresser.current.trigger;
CrossDresser.on = CrossDresser.current.on;
})(CrossDresser || (CrossDresser = {}));
;