betajs-browser
Version:
BetaJS-Browser is a client-side JavaScript framework for Browser-specific methods.
1,649 lines (1,466 loc) • 180 kB
JavaScript
/*!
betajs-browser - v1.0.138 - 2023-03-03
Copyright (c) Oliver Friedmann,Rashad Aliyev
Apache-2.0 Software License.
*/
/** @flow **//*!
betajs-scoped - v0.0.22 - 2019-10-23
Copyright (c) Oliver Friedmann
Apache-2.0 Software License.
*/
var Scoped = (function () {
var Globals = (function () {
/**
* This helper module provides functions for reading and writing globally accessible namespaces, both in the browser and in NodeJS.
*
* @module Globals
* @access private
*/
return {
/**
* Returns the value of a global variable.
*
* @param {string} key identifier of a global variable
* @return value of global variable or undefined if not existing
*/
get : function(key/* : string */) {
if (typeof window !== "undefined")
return key ? window[key] : window;
if (typeof global !== "undefined")
return key ? global[key] : global;
if (typeof self !== "undefined")
return key ? self[key] : self;
return undefined;
},
/**
* Sets a global variable.
*
* @param {string} key identifier of a global variable
* @param value value to be set
* @return value that has been set
*/
set : function(key/* : string */, value) {
if (typeof window !== "undefined")
window[key] = value;
if (typeof global !== "undefined")
global[key] = value;
if (typeof self !== "undefined")
self[key] = value;
return value;
},
/**
* Returns the value of a global variable under a namespaced path.
*
* @param {string} path namespaced path identifier of variable
* @return value of global variable or undefined if not existing
*
* @example
* // returns window.foo.bar / global.foo.bar
* Globals.getPath("foo.bar")
*/
getPath: function (path/* : string */) {
if (!path)
return this.get();
var args = path.split(".");
if (args.length == 1)
return this.get(path);
var current = this.get(args[0]);
for (var i = 1; i < args.length; ++i) {
if (!current)
return current;
current = current[args[i]];
}
return current;
},
/**
* Sets a global variable under a namespaced path.
*
* @param {string} path namespaced path identifier of variable
* @param value value to be set
* @return value that has been set
*
* @example
* // sets window.foo.bar / global.foo.bar
* Globals.setPath("foo.bar", 42);
*/
setPath: function (path/* : string */, value) {
var args = path.split(".");
if (args.length == 1)
return this.set(path, value);
var current = this.get(args[0]) || this.set(args[0], {});
for (var i = 1; i < args.length - 1; ++i) {
if (!(args[i] in current))
current[args[i]] = {};
current = current[args[i]];
}
current[args[args.length - 1]] = value;
return value;
}
};}).call(this);
/*::
declare module Helper {
declare function extend<A, B>(a: A, b: B): A & B;
}
*/
var Helper = (function () {
/**
* This helper module provides auxiliary functions for the Scoped system.
*
* @module Helper
* @access private
*/
return {
/**
* Attached a context to a function.
*
* @param {object} obj context for the function
* @param {function} func function
*
* @return function with attached context
*/
method: function (obj, func) {
return function () {
return func.apply(obj, arguments);
};
},
/**
* Extend a base object with all attributes of a second object.
*
* @param {object} base base object
* @param {object} overwrite second object
*
* @return {object} extended base object
*/
extend: function (base, overwrite) {
base = base || {};
overwrite = overwrite || {};
for (var key in overwrite)
base[key] = overwrite[key];
return base;
},
/**
* Returns the type of an object, particulary returning 'array' for arrays.
*
* @param obj object in question
*
* @return {string} type of object
*/
typeOf: function (obj) {
return Object.prototype.toString.call(obj) === '[object Array]' ? "array" : typeof obj;
},
/**
* Returns whether an object is null, undefined, an empty array or an empty object.
*
* @param obj object in question
*
* @return true if object is empty
*/
isEmpty: function (obj) {
if (obj === null || typeof obj === "undefined")
return true;
if (this.typeOf(obj) == "array")
return obj.length === 0;
if (typeof obj !== "object")
return false;
for (var key in obj)
return false;
return true;
},
/**
* Matches function arguments against some pattern.
*
* @param {array} args function arguments
* @param {object} pattern typed pattern
*
* @return {object} matched arguments as associative array
*/
matchArgs: function (args, pattern) {
var i = 0;
var result = {};
for (var key in pattern) {
if (pattern[key] === true || this.typeOf(args[i]) == pattern[key]) {
result[key] = args[i];
i++;
} else if (this.typeOf(args[i]) == "undefined")
i++;
}
return result;
},
/**
* Stringifies a value as JSON and functions to string representations.
*
* @param value value to be stringified
*
* @return stringified value
*/
stringify: function (value) {
if (this.typeOf(value) == "function")
return "" + value;
return JSON.stringify(value);
}
};}).call(this);
var Attach = (function () {
/**
* This module provides functionality to attach the Scoped system to the environment.
*
* @module Attach
* @access private
*/
return {
__namespace: "Scoped",
__revert: null,
/**
* Upgrades a pre-existing Scoped system to the newest version present.
*
* @param {string} namespace Optional namespace (default is 'Scoped')
* @return {object} the attached Scoped system
*/
upgrade: function (namespace/* : ?string */) {
var current = Globals.get(namespace || Attach.__namespace);
if (current && Helper.typeOf(current) === "object" && current.guid === this.guid && Helper.typeOf(current.version) === "string") {
if (this.upgradable === false || current.upgradable === false)
return current;
var my_version = this.version.split(".");
var current_version = current.version.split(".");
var newer = false;
for (var i = 0; i < Math.min(my_version.length, current_version.length); ++i) {
newer = parseInt(my_version[i], 10) > parseInt(current_version[i], 10);
if (my_version[i] !== current_version[i])
break;
}
return newer ? this.attach(namespace) : current;
} else
return this.attach(namespace);
},
/**
* Attaches the Scoped system to the environment.
*
* @param {string} namespace Optional namespace (default is 'Scoped')
* @return {object} the attached Scoped system
*/
attach : function(namespace/* : ?string */) {
if (namespace)
Attach.__namespace = namespace;
var current = Globals.get(Attach.__namespace);
if (current === this)
return this;
Attach.__revert = current;
if (current) {
try {
var exported = current.__exportScoped();
this.__exportBackup = this.__exportScoped();
this.__importScoped(exported);
} catch (e) {
// We cannot upgrade the old version.
}
}
Globals.set(Attach.__namespace, this);
return this;
},
/**
* Detaches the Scoped system from the environment.
*
* @param {boolean} forceDetach Overwrite any attached scoped system by null.
* @return {object} the detached Scoped system
*/
detach: function (forceDetach/* : ?boolean */) {
if (forceDetach)
Globals.set(Attach.__namespace, null);
if (typeof Attach.__revert != "undefined")
Globals.set(Attach.__namespace, Attach.__revert);
delete Attach.__revert;
if (Attach.__exportBackup)
this.__importScoped(Attach.__exportBackup);
return this;
},
/**
* Exports an object as a module if possible.
*
* @param {object} mod a module object (optional, default is 'module')
* @param {object} object the object to be exported
* @param {boolean} forceExport overwrite potentially pre-existing exports
* @return {object} the Scoped system
*/
exports: function (mod, object, forceExport) {
mod = mod || (typeof module != "undefined" ? module : null);
if (typeof mod == "object" && mod && "exports" in mod && (forceExport || mod.exports === this || !mod.exports || Helper.isEmpty(mod.exports)))
mod.exports = object || this;
return this;
}
};}).call(this);
function newNamespace (opts/* : {tree ?: boolean, global ?: boolean, root ?: Object} */) {
var options/* : {
tree: boolean,
global: boolean,
root: Object
} */ = {
tree: typeof opts.tree === "boolean" ? opts.tree : false,
global: typeof opts.global === "boolean" ? opts.global : false,
root: typeof opts.root === "object" ? opts.root : {}
};
/*::
type Node = {
route: ?string,
parent: ?Node,
children: any,
watchers: any,
data: any,
ready: boolean,
lazy: any
};
*/
function initNode(options)/* : Node */ {
return {
route: typeof options.route === "string" ? options.route : null,
parent: typeof options.parent === "object" ? options.parent : null,
ready: typeof options.ready === "boolean" ? options.ready : false,
children: {},
watchers: [],
data: {},
lazy: []
};
}
var nsRoot = initNode({ready: true});
if (options.tree) {
if (options.global) {
try {
if (window)
nsRoot.data = window;
} catch (e) { }
try {
if (global)
nsRoot.data = global;
} catch (e) { }
try {
if (self)
nsRoot.data = self;
} catch (e) { }
} else
nsRoot.data = options.root;
}
function nodeDigest(node/* : Node */) {
if (node.ready)
return;
if (node.parent && !node.parent.ready) {
nodeDigest(node.parent);
return;
}
if (node.route && node.parent && (node.route in node.parent.data)) {
node.data = node.parent.data[node.route];
node.ready = true;
for (var i = 0; i < node.watchers.length; ++i)
node.watchers[i].callback.call(node.watchers[i].context || this, node.data);
node.watchers = [];
for (var key in node.children)
nodeDigest(node.children[key]);
}
}
function nodeEnforce(node/* : Node */) {
if (node.ready)
return;
if (node.parent && !node.parent.ready)
nodeEnforce(node.parent);
node.ready = true;
if (node.parent) {
if (options.tree && typeof node.parent.data == "object")
node.parent.data[node.route] = node.data;
}
for (var i = 0; i < node.watchers.length; ++i)
node.watchers[i].callback.call(node.watchers[i].context || this, node.data);
node.watchers = [];
}
function nodeSetData(node/* : Node */, value) {
if (typeof value == "object" && node.ready) {
for (var key in value)
node.data[key] = value[key];
} else
node.data = value;
if (typeof value == "object") {
for (var ckey in value) {
if (node.children[ckey])
node.children[ckey].data = value[ckey];
}
}
nodeEnforce(node);
for (var k in node.children)
nodeDigest(node.children[k]);
}
function nodeClearData(node/* : Node */) {
if (node.ready && node.data) {
for (var key in node.data)
delete node.data[key];
}
}
function nodeNavigate(path/* : ?String */) {
if (!path)
return nsRoot;
var routes = path.split(".");
var current = nsRoot;
for (var i = 0; i < routes.length; ++i) {
if (routes[i] in current.children)
current = current.children[routes[i]];
else {
current.children[routes[i]] = initNode({
parent: current,
route: routes[i]
});
current = current.children[routes[i]];
nodeDigest(current);
}
}
return current;
}
function nodeAddWatcher(node/* : Node */, callback, context) {
if (node.ready)
callback.call(context || this, node.data);
else {
node.watchers.push({
callback: callback,
context: context
});
if (node.lazy.length > 0) {
var f = function (node) {
if (node.lazy.length > 0) {
var lazy = node.lazy.shift();
lazy.callback.call(lazy.context || this, node.data);
f(node);
}
};
f(node);
}
}
}
function nodeUnresolvedWatchers(node/* : Node */, base, result) {
node = node || nsRoot;
result = result || [];
if (!node.ready && node.lazy.length === 0 && node.watchers.length > 0)
result.push(base);
for (var k in node.children) {
var c = node.children[k];
var r = (base ? base + "." : "") + c.route;
result = nodeUnresolvedWatchers(c, r, result);
}
return result;
}
/**
* The namespace module manages a namespace in the Scoped system.
*
* @module Namespace
* @access public
*/
return {
/**
* Extend a node in the namespace by an object.
*
* @param {string} path path to the node in the namespace
* @param {object} value object that should be used for extend the namespace node
*/
extend: function (path, value) {
nodeSetData(nodeNavigate(path), value);
},
/**
* Set the object value of a node in the namespace.
*
* @param {string} path path to the node in the namespace
* @param {object} value object that should be used as value for the namespace node
*/
set: function (path, value) {
var node = nodeNavigate(path);
if (node.data)
nodeClearData(node);
nodeSetData(node, value);
},
/**
* Read the object value of a node in the namespace.
*
* @param {string} path path to the node in the namespace
* @return {object} object value of the node or null if undefined
*/
get: function (path) {
var node = nodeNavigate(path);
return node.ready ? node.data : null;
},
/**
* Lazily navigate to a node in the namespace.
* Will asynchronously call the callback as soon as the node is being touched.
*
* @param {string} path path to the node in the namespace
* @param {function} callback callback function accepting the node's object value
* @param {context} context optional callback context
*/
lazy: function (path, callback, context) {
var node = nodeNavigate(path);
if (node.ready)
callback(context || this, node.data);
else {
node.lazy.push({
callback: callback,
context: context
});
}
},
/**
* Digest a node path, checking whether it has been defined by an external system.
*
* @param {string} path path to the node in the namespace
*/
digest: function (path) {
nodeDigest(nodeNavigate(path));
},
/**
* Asynchronously access a node in the namespace.
* Will asynchronously call the callback as soon as the node is being defined.
*
* @param {string} path path to the node in the namespace
* @param {function} callback callback function accepting the node's object value
* @param {context} context optional callback context
*/
obtain: function (path, callback, context) {
nodeAddWatcher(nodeNavigate(path), callback, context);
},
/**
* Returns all unresolved watchers under a certain path.
*
* @param {string} path path to the node in the namespace
* @return {array} list of all unresolved watchers
*/
unresolvedWatchers: function (path) {
return nodeUnresolvedWatchers(nodeNavigate(path), path);
},
__export: function () {
return {
options: options,
nsRoot: nsRoot
};
},
__import: function (data) {
options = data.options;
nsRoot = data.nsRoot;
}
};
}
function newScope (parent, parentNS, rootNS, globalNS) {
var self = this;
var nextScope = null;
var childScopes = [];
var parentNamespace = parentNS;
var rootNamespace = rootNS;
var globalNamespace = globalNS;
var localNamespace = newNamespace({tree: true});
var privateNamespace = newNamespace({tree: false});
var bindings = {
"global": {
namespace: globalNamespace
}, "root": {
namespace: rootNamespace
}, "local": {
namespace: localNamespace
}, "default": {
namespace: privateNamespace
}, "parent": {
namespace: parentNamespace
}, "scope": {
namespace: localNamespace,
readonly: false
}
};
var custom = function (argmts, name, callback) {
var args = Helper.matchArgs(argmts, {
options: "object",
namespaceLocator: true,
dependencies: "array",
hiddenDependencies: "array",
callback: true,
context: "object"
});
var options = Helper.extend({
lazy: this.options.lazy
}, args.options || {});
var ns = this.resolve(args.namespaceLocator);
var execute = function () {
this.require(args.dependencies, args.hiddenDependencies, function () {
var _arguments = [];
for (var a = 0; a < arguments.length; ++a)
_arguments.push(arguments[a]);
_arguments[_arguments.length - 1].ns = ns;
if (this.options.compile) {
var params = [];
for (var i = 0; i < argmts.length; ++i)
params.push(Helper.stringify(argmts[i]));
this.compiled += this.options.ident + "." + name + "(" + params.join(", ") + ");\n\n";
}
if (this.options.dependencies) {
this.dependencies[ns.path] = this.dependencies[ns.path] || {};
if (args.dependencies) {
args.dependencies.forEach(function (dep) {
this.dependencies[ns.path][this.resolve(dep).path] = true;
}, this);
}
if (args.hiddenDependencies) {
args.hiddenDependencies.forEach(function (dep) {
this.dependencies[ns.path][this.resolve(dep).path] = true;
}, this);
}
}
var result = this.options.compile ? {} : args.callback.apply(args.context || this, _arguments);
callback.call(this, ns, result);
}, this);
};
if (options.lazy)
ns.namespace.lazy(ns.path, execute, this);
else
execute.apply(this);
return this;
};
/**
* This module provides all functionality in a scope.
*
* @module Scoped
* @access public
*/
return {
getGlobal: Helper.method(Globals, Globals.getPath),
setGlobal: Helper.method(Globals, Globals.setPath),
options: {
lazy: false,
ident: "Scoped",
compile: false,
dependencies: false
},
compiled: "",
dependencies: {},
/**
* Returns a reference to the next scope that will be obtained by a subScope call.
*
* @return {object} next scope
*/
nextScope: function () {
if (!nextScope)
nextScope = newScope(this, localNamespace, rootNamespace, globalNamespace);
return nextScope;
},
/**
* Creates a sub scope of the current scope and returns it.
*
* @return {object} sub scope
*/
subScope: function () {
var sub = this.nextScope();
childScopes.push(sub);
nextScope = null;
return sub;
},
/**
* Creates a binding within in the scope.
*
* @param {string} alias identifier of the new binding
* @param {string} namespaceLocator identifier of an existing namespace path
* @param {object} options options for the binding
*
*/
binding: function (alias, namespaceLocator, options) {
if (!bindings[alias] || !bindings[alias].readonly) {
var ns;
if (Helper.typeOf(namespaceLocator) != "string") {
ns = {
namespace: newNamespace({
tree: true,
root: namespaceLocator
}),
path: null
};
} else
ns = this.resolve(namespaceLocator);
bindings[alias] = Helper.extend(options, ns);
}
return this;
},
/**
* Resolves a name space locator to a name space.
*
* @param {string} namespaceLocator name space locator
* @return {object} resolved name space
*
*/
resolve: function (namespaceLocator) {
var parts = namespaceLocator.split(":");
if (parts.length == 1) {
throw ("The locator '" + parts[0] + "' requires a namespace.");
} else {
var binding = bindings[parts[0]];
if (!binding)
throw ("The namespace '" + parts[0] + "' has not been defined (yet).");
return {
namespace: binding.namespace,
path : binding.path && parts[1] ? binding.path + "." + parts[1] : (binding.path || parts[1])
};
}
},
/**
* Defines a new name space once a list of name space locators is available.
*
* @param {string} namespaceLocator the name space that is to be defined
* @param {array} dependencies a list of name space locator dependencies (optional)
* @param {array} hiddenDependencies a list of hidden name space locators (optional)
* @param {function} callback a callback function accepting all dependencies as arguments and returning the new definition
* @param {object} context a callback context (optional)
*
*/
define: function () {
return custom.call(this, arguments, "define", function (ns, result) {
if (ns.namespace.get(ns.path))
throw ("Scoped namespace " + ns.path + " has already been defined. Use extend to extend an existing namespace instead");
ns.namespace.set(ns.path, result);
});
},
/**
* Assume a specific version of a module and fail if it is not met.
*
* @param {string} assumption name space locator
* @param {string} version assumed version
*
*/
assumeVersion: function () {
var args = Helper.matchArgs(arguments, {
assumption: true,
dependencies: "array",
callback: true,
context: "object",
error: "string"
});
var dependencies = args.dependencies || [];
dependencies.unshift(args.assumption);
this.require(dependencies, function () {
var argv = arguments;
var assumptionValue = argv[0].replace(/[^\d\.]/g, "");
argv[0] = assumptionValue.split(".");
for (var i = 0; i < argv[0].length; ++i)
argv[0][i] = parseInt(argv[0][i], 10);
if (Helper.typeOf(args.callback) === "function") {
if (!args.callback.apply(args.context || this, args))
throw ("Scoped Assumption '" + args.assumption + "' failed, value is " + assumptionValue + (args.error ? ", but assuming " + args.error : ""));
} else {
var version = (args.callback + "").replace(/[^\d\.]/g, "").split(".");
for (var j = 0; j < Math.min(argv[0].length, version.length); ++j)
if (parseInt(version[j], 10) > argv[0][j])
throw ("Scoped Version Assumption '" + args.assumption + "' failed, value is " + assumptionValue + ", but assuming at least " + args.callback);
}
});
},
/**
* Extends a potentially existing name space once a list of name space locators is available.
*
* @param {string} namespaceLocator the name space that is to be defined
* @param {array} dependencies a list of name space locator dependencies (optional)
* @param {array} hiddenDependencies a list of hidden name space locators (optional)
* @param {function} callback a callback function accepting all dependencies as arguments and returning the new additional definitions.
* @param {object} context a callback context (optional)
*
*/
extend: function () {
return custom.call(this, arguments, "extend", function (ns, result) {
ns.namespace.extend(ns.path, result);
});
},
/**
* Requires a list of name space locators and calls a function once they are present.
*
* @param {array} dependencies a list of name space locator dependencies (optional)
* @param {array} hiddenDependencies a list of hidden name space locators (optional)
* @param {function} callback a callback function accepting all dependencies as arguments
* @param {object} context a callback context (optional)
*
*/
require: function () {
var args = Helper.matchArgs(arguments, {
dependencies: "array",
hiddenDependencies: "array",
callback: "function",
context: "object"
});
args.callback = args.callback || function () {};
var dependencies = args.dependencies || [];
var allDependencies = dependencies.concat(args.hiddenDependencies || []);
var count = allDependencies.length;
var deps = [];
var environment = {};
if (count) {
var f = function (value) {
if (this.i < deps.length)
deps[this.i] = value;
count--;
if (count === 0) {
deps.push(environment);
args.callback.apply(args.context || this.ctx, deps);
}
};
for (var i = 0; i < allDependencies.length; ++i) {
var ns = this.resolve(allDependencies[i]);
if (i < dependencies.length)
deps.push(null);
ns.namespace.obtain(ns.path, f, {
ctx: this,
i: i
});
}
} else {
deps.push(environment);
args.callback.apply(args.context || this, deps);
}
return this;
},
/**
* Digest a name space locator, checking whether it has been defined by an external system.
*
* @param {string} namespaceLocator name space locator
*/
digest: function (namespaceLocator) {
var ns = this.resolve(namespaceLocator);
ns.namespace.digest(ns.path);
return this;
},
/**
* Returns all unresolved definitions under a namespace locator
*
* @param {string} namespaceLocator name space locator, e.g. "global:"
* @return {array} list of all unresolved definitions
*/
unresolved: function (namespaceLocator) {
var ns = this.resolve(namespaceLocator);
return ns.namespace.unresolvedWatchers(ns.path);
},
/**
* Exports the scope.
*
* @return {object} exported scope
*/
__export: function () {
return {
parentNamespace: parentNamespace.__export(),
rootNamespace: rootNamespace.__export(),
globalNamespace: globalNamespace.__export(),
localNamespace: localNamespace.__export(),
privateNamespace: privateNamespace.__export()
};
},
/**
* Imports a scope from an exported scope.
*
* @param {object} data exported scope to be imported
*
*/
__import: function (data) {
parentNamespace.__import(data.parentNamespace);
rootNamespace.__import(data.rootNamespace);
globalNamespace.__import(data.globalNamespace);
localNamespace.__import(data.localNamespace);
privateNamespace.__import(data.privateNamespace);
}
};
}
var globalNamespace = newNamespace({tree: true, global: true});
var rootNamespace = newNamespace({tree: true});
var rootScope = newScope(null, rootNamespace, rootNamespace, globalNamespace);
var Public = Helper.extend(rootScope, (function () {
/**
* This module includes all public functions of the Scoped system.
*
* It includes all methods of the root scope and the Attach module.
*
* @module Public
* @access public
*/
return {
guid: "4b6878ee-cb6a-46b3-94ac-27d91f58d666",
version: '0.0.22',
upgradable: true,
upgrade: Attach.upgrade,
attach: Attach.attach,
detach: Attach.detach,
exports: Attach.exports,
/**
* Exports all data contained in the Scoped system.
*
* @return data of the Scoped system.
* @access private
*/
__exportScoped: function () {
return {
globalNamespace: globalNamespace.__export(),
rootNamespace: rootNamespace.__export(),
rootScope: rootScope.__export()
};
},
/**
* Import data into the Scoped system.
*
* @param data of the Scoped system.
* @access private
*/
__importScoped: function (data) {
globalNamespace.__import(data.globalNamespace);
rootNamespace.__import(data.rootNamespace);
rootScope.__import(data.rootScope);
}
};
}).call(this));
Public = Public.upgrade();
Public.exports();
return Public;
}).call(this);
/*!
betajs-browser - v1.0.138 - 2023-03-03
Copyright (c) Oliver Friedmann,Rashad Aliyev
Apache-2.0 Software License.
*/
(function () {
var Scoped = this.subScope();
Scoped.binding('module', 'global:BetaJS.Browser');
Scoped.binding('base', 'global:BetaJS');
Scoped.define("module:", function () {
return {
"guid": "02450b15-9bbf-4be2-b8f6-b483bc015d06",
"version": "1.0.138",
"datetime": 1677885475806
};
});
Scoped.assumeVersion('base:version', '~1.0.104');
Scoped.define("module:Ajax.IframePostmessageAjax", [
"base:Ajax.Support",
"base:Net.Uri",
"base:Net.HttpHeader",
"base:Promise",
"base:Types",
"base:Ajax.RequestException",
"base:Tokens",
"base:Objs"
], function(AjaxSupport, Uri, HttpHeader, Promise, Types, RequestException, Tokens, Objs) {
var id = 1;
var Module = {
supports: function(options) {
if (!options.postmessage)
return false;
return true;
},
execute: function(options) {
var postmessageName = "postmessage_" + Tokens.generate_token() + "_" + (id++);
var params = Objs.objectBy(options.postmessage, postmessageName);
params = Objs.extend(params, options.query);
var uri = Uri.appendUriParams(options.uri, params);
var iframe = document.createElement("iframe");
iframe.id = postmessageName;
iframe.name = postmessageName;
iframe.style.display = "none";
var form = document.createElement("form");
form.method = options.method;
form.target = postmessageName;
uri = AjaxSupport.finalizeUri(options, uri);
form.action = uri;
form.style.display = "none";
var promise = Promise.create();
document.body.appendChild(iframe);
document.body.appendChild(form);
Objs.iter(options.data, function(value, key) {
var input = document.createElement("input");
input.type = "hidden";
input.name = key;
input.value = Types.is_array(value) || Types.is_object(value) ? JSON.stringify(value) : value;
form.appendChild(input);
}, this);
var post_message_fallback = !("postMessage" in window);
var self = this;
var handle_success = null;
var message_event_handler = function(event) {
handle_success(event.data);
};
handle_success = function(raw_data) {
if (typeof raw_data === "string")
raw_data = JSON.parse(raw_data);
if (!(postmessageName in raw_data))
return;
raw_data = raw_data[postmessageName];
if (post_message_fallback)
window.postMessage = null;
window.removeEventListener("message", message_event_handler, false);
document.body.removeChild(form);
document.body.removeChild(iframe);
AjaxSupport.promiseReturnData(promise, options, raw_data, "json"); //options.decodeType);
};
iframe.onerror = function() {
if (post_message_fallback)
window.postMessage = null;
window.removeEventListener("message", message_event_handler, false);
document.body.removeChild(form);
document.body.removeChild(iframe);
// TODO
//AjaxSupport.promiseRequestException(promise, xmlhttp.status, xmlhttp.statusText, xmlhttp.responseText, "json"); //options.decodeType);)
};
window.addEventListener("message", message_event_handler, false);
if (post_message_fallback)
window.postMessage = handle_success;
form.submit();
return promise;
}
};
AjaxSupport.register(Module, 4);
return Module;
});
Scoped.define("module:Ajax.JsonpScriptAjax", [
"base:Ajax.Support",
"base:Net.Uri",
"base:Net.HttpHeader",
"base:Promise",
"base:Types",
"base:Ajax.RequestException",
"base:Tokens",
"base:Objs",
"base:Async",
"module:Info"
], function(AjaxSupport, Uri, HttpHeader, Promise, Types, RequestException, Tokens, Objs, Async, Info) {
var id = 1;
var Module = {
supports: function(options) {
if (!options.jsonp)
return false;
if (options.method !== "GET")
return false;
return true;
},
execute: function(options) {
var callbackName = "jsonp_" + Tokens.generate_token() + "_" + (id++);
var params = Objs.objectBy(options.jsonp, callbackName);
params = Objs.extend(params, options.query);
params = Objs.extend(params, options.data);
var uri = Uri.appendUriParams(options.uri, params);
var hasResult = false;
window[callbackName] = function(data) {
if (hasResult)
return;
hasResult = true;
try {
delete window[callbackName];
} catch (e) {
window[callbackName] = undefined;
}
AjaxSupport.promiseReturnData(promise, options, data, "json"); //options.decodeType);
};
var promise = Promise.create();
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
var executed = false;
script.onerror = function(event) {
if (event) {
if (event.stopPropagation)
event.stopPropagation();
else
event.cancelBubble = true;
}
if (hasResult)
return;
hasResult = true;
AjaxSupport.promiseRequestException(promise, HttpHeader.HTTP_STATUS_BAD_REQUEST, HttpHeader.format(HttpHeader.HTTP_STATUS_BAD_REQUEST), null, "json"); //options.decodeType);)
};
script.onload = script.onreadystatechange = function() {
if (!executed && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete")) {
executed = true;
script.onload = script.onreadystatechange = null;
head.removeChild(script);
if (Info.isInternetExplorer() && Info.internetExplorerVersion() < 9) {
Async.eventually(function() {
if (!hasResult)
script.onerror();
});
}
}
};
uri = AjaxSupport.finalizeUri(options, uri);
script.src = uri;
head.appendChild(script);
return promise;
}
};
AjaxSupport.register(Module, 5);
return Module;
});
Scoped.define("module:Ajax.XDomainRequestAjax", [
"base:Ajax.Support",
"base:Net.Uri",
"base:Net.HttpHeader",
"base:Promise",
"base:Types",
"base:Ajax.RequestException",
"module:Info",
"base:Async",
"base:Ids"
], function(AjaxSupport, Uri, HttpHeader, Promise, Types, RequestException, Info, Async, Ids) {
var Module = {
// IE Garbage Collection for XDomainRequest is broken
__requests: {},
supports: function(options) {
if (!window.XDomainRequest)
return false;
if (options.forceJsonp || options.forcePostmessage)
return false;
if (!options.isCorsRequest)
return false;
if (!Info.isInternetExplorer() || Info.internetExplorerVersion() > 9)
return false;
// TODO: Check Data
return true;
},
execute: function(options) {
var uri = Uri.appendUriParams(options.uri, options.query || {});
if (options.method === "GET")
uri = Uri.appendUriParams(uri, options.data || {});
var promise = Promise.create();
var xdomreq = new XDomainRequest();
Module.__requests[Ids.objectId(xdomreq)] = xdomreq;
xdomreq.onload = function() {
// TODO: Figure out response type.
AjaxSupport.promiseReturnData(promise, options, xdomreq.responseText, "json"); //options.decodeType);
delete Module.__requests[Ids.objectId(xdomreq)];
};
xdomreq.ontimeout = function() {
AjaxSupport.promiseRequestException(promise, HttpHeader.HTTP_STATUS_GATEWAY_TIMEOUT, HttpHeader.format(HttpHeader.HTTP_STATUS_GATEWAY_TIMEOUT), null, "json"); //options.decodeType);)
delete Module.__requests[Ids.objectId(xdomreq)];
};
xdomreq.onerror = function() {
AjaxSupport.promiseRequestException(promise, HttpHeader.HTTP_STATUS_BAD_REQUEST, HttpHeader.format(HttpHeader.HTTP_STATUS_BAD_REQUEST), null, "json"); //options.decodeType);)
delete Module.__requests[Ids.objectId(xdomreq)];
};
uri = AjaxSupport.finalizeUri(options, uri);
xdomreq.open(options.method, uri);
Async.eventually(function() {
if (options.method !== "GET" && !Types.is_empty(options.data)) {
if (options.contentType === "json")
xdomreq.send(JSON.stringify(options.data));
else {
xdomreq.send(Uri.encodeUriParams(options.data, undefined, true));
}
} else
xdomreq.send();
}, this);
return promise;
}
};
AjaxSupport.register(Module, 9);
return Module;
});
Scoped.define("module:Ajax.XmlHttpRequestAjax", [
"base:Ajax.Support",
"base:Net.Uri",
"base:Net.HttpHeader",
"base:Promise",
"base:Types",
"base:Objs",
"base:Ajax.RequestException",
"module:Info"
], function(AjaxSupport, Uri, HttpHeader, Promise, Types, Objs, RequestException, Info) {
var Module = {
supports: function(options) {
// Worker
if (typeof window === "undefined")
return true;
if (!window.XMLHttpRequest)
return false;
if (options.forceJsonp || options.forcePostmessage)
return false;
if (Info.isInternetExplorer() && Info.internetExplorerVersion() < 10 && options.isCorsRequest)
return false;
try {
Objs.iter(options.data, function(value) {
if ((typeof(window.Blob) !== "undefined" && value instanceof(window.Blob)) || (typeof File !== "undefined" && value instanceof File))
options.requireFormData = true;
});
if (options.requireFormData)
new(window.FormData)();
} catch (e) {
options.requireFormData = false;
}
return true;
},
create: function() {
return new XMLHttpRequest();
},
execute: function(options, progress, progressCtx, xmlhttp) {
var uri = Uri.appendUriParams(options.uri, options.query || {});
if (!options.methodSupportsPayload)
uri = Uri.appendUriParams(uri, options.data || {});
var promise = Promise.create();
xmlhttp = xmlhttp || this.create();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === 4) {
if (HttpHeader.isSuccessStatus(xmlhttp.status) || (xmlhttp.status === 0 && xmlhttp.responseText)) {
AjaxSupport.promiseReturnData(promise, options, options.contentType === "binary" ? xmlhttp.response : (options.contentType === "xml" ? xmlhttp.responseXML : xmlhttp.responseText), options.decodeType || "json");
} else {
AjaxSupport.promiseRequestException(promise, xmlhttp.status, xmlhttp.statusText, xmlhttp.responseText, options.decodeType || "json");
}
}
};
if (progress) {
(xmlhttp.upload || xmlhttp).onprogress = function(e) {
if (e.lengthComputable)
progress.call(progressCtx || this, e.loaded, e.total);
};
}
uri = AjaxSupport.finalizeUri(options, uri);
var parsed = Uri.parse(uri);
if (Info.isFirefox() && parsed.user && parsed.password)
uri = uri.replace(parsed.user + ":" + parsed.password + "@", "");
xmlhttp.open(options.method, uri, true);
if (options.corscreds)
xmlhttp.withCredentials = true;
if (options.bearer)
xmlhttp.setRequestHeader('Authorization', 'Bearer ' + options.bearer);
if (options.accept)
xmlhttp.setRequestHeader("Accept", options.accept);
if (options.contentType === "binary")
xmlhttp.responseType = "blob";
if (parsed.user || parsed.password)
xmlhttp.setRequestHeader('Authorization', 'Basic ' + btoa(parsed.user + ':' + parsed.password));
if (options.methodSupportsPayload && !Types.is_empty(options.data)) {
if (options.noFormData) {
xmlhttp.send(options.data.file);
} else if (options.requireFormData) {
var formData = new(window.FormData)();
Objs.iter(options.data, function(value, key) {
formData.append(key, value);
}, this);
// xmlhttp.setRequestHeader("Content-Type", "multipart/form-data");
xmlhttp.send(formData);
} else if (options.contentType === "json") {
if (options.sendContentType)
xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xmlhttp.send(JSON.stringify(options.data));
} else if (options.contentType === "xml") {
xmlhttp.overrideMimeType('application/xml');
xmlhttp.send(JSON.stringify(options.data));
} else {
if (options.sendContentType)
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send(Uri.encodeUriParams(options.data, undefined, true));
}
} else
xmlhttp.send();
return promise;
}
};
AjaxSupport.register(Module, 10);
return Module;
});
Scoped.define("module:Apps", [
"base:Time",
"base:Async",
"base:Promise",
"module:Info",
"module:Loader"
], function(Time, Async, Promise, Info, Loader) {
return {
STATE_INCOMPATIBLE_DEVICE: 1,
STATE_APP_LAUNCHED: 2,
STATE_APP_INSTALLED_AND_LAUNCHED: 3,
STATE_APP_NOT_INSTALLED: 4,
STATE_UNKNOWN: 5,
//ios.launch, ios.install, android.intent, android.launch, android.install
launch: function(options) {
var promise = Promise.create();
var start = Time.now();
if (Info.isiOS() && options.ios) {
Async.eventually(function() {
if (Time.now() - start > 3000)
promise.asyncSuccess(this.STATE_APP_LAUNCHED);
else {
start = Time.now();
Async.eventually(function() {
if (Time.now() - start > 3000)
promise.asyncSuccess(this.STATE_APP_INSTALLED_AND_LAUNCHED);
else
promise.asyncError(this.STATE_APP_NOT_INSTALLED);
}, this, 2500);
document.location = options.ios.install;
}
}, this, 2500);
document.location = options.ios.launch;
} else
/*if (Info.isAndroid() && options.android) {
if (Info.isOpera()) {
Loader.loadByIFrame({
url: options.android.launch
}, function () {
document.location
}, this);
} else if (Info.isFirefox()) {
} else {
document.location = options.android.intent;
promise.asyncSuccess(this.STATE_UNKNOWN);
}
} else*/
promise.asyncError(this.STATE_INCOMPATIBLE_DEVICE);
return promise;
},
appStoreLink: function(appIdent) {
return "itms://itunes.apple.com/us/app/" + appIdent + "?mt=8&uo=4";
},
playStoreLink: function(appIdent) {
return "https://play.google.com/store/apps/details?id=<" + appIdent + ">";
},
iOSAppURL: function(protocol, url) {
return protocol + "://" + url;
},
androidAppUrl: function(protocol, url) {
return protocol + "://" + url;
},
googleIntent: function(protocol, url, appIdent) {
return "intent://" + url + ";scheme=" + protocol + ";package=" + appIdent + ";end";
}
};
});
/*
function launchAndroidApp(el) {
heartbeat = setInterval(intervalHeartbeat, 200);
if (navigator.userAgent.match(/Opera/) || navigator.userAgent.match(/OPR/)) {
tryIframeApproach();
} else if (navigator.userAgent.match(/Firefox/)) {
webkitApproach();
iframe_timer = setTimeout(function () {
tryIframeApproach();
}, 1500);
} else if (navigator.userAgent.match(/Chrome/)) {
document.location = googleIntent; // Use google intent
} else { // Native browser ?
document.location = googleIntent; // Use google intent
}
}
function webkitApproach() {
document.location = nativeAndroidUrl;
timer = setTimeout(function () {
document.location = googlePlayStore;
}, 2500);
}
function clearTimers() {
clearTimeout(timer);
clearTimeout(heartbeat);
clearTimeout(iframe_timer);
}
function intervalHeartbeat() {
if (document.webkitHidden || document.hidden) {
clearTimers();
}
}
function tryIframeApproach() {
var iframe = document.createElement("iframe");
iframe.style.border = "none";
iframe.style.width = "1px";
iframe.style.height = "1px";
iframe.onload = function () {
document.location = googlePlayStore;
};
iframe.src = nativeAndroidUrl;
document.body.appendChild(iframe);
}
*/
Scoped.define("module:Blobs", [
"base:Promise"
], function(Promise) {
return {
createBlobByArrayBufferView: function(arrayBuffer, offset, size, type) {
try {
return new(window.Blob)([new DataView(arrayBuffer, offset, size)], {
type: type
});
} catch (err) {
try {
return new(window.Blob)([new Uint8Array(arrayBuffer, offset, size)], {
type: type
});
} catch (err2) {
var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
var bb = new BlobBuilder();
bb.append(arrayBuffer.slice(offset, offset + size));
return bb.getBlob(type);
}
}
},
loadFileIntoArrayBuffer: function(file) {
var promise = Promise.create();
try {
var fileReader = new FileReader();
fileReader.onloadend = function(ev) {
promise.asyncSuccess(ev.target.result);
};
fileReader.readAsArrayBuffer(file.files ? file.files[0] : file);
} catch (err) {
promise.asyncError(err);
}
return promise;
},
loadFileIntoString: function(file) {
var promise = Promise.create();
try {
var fileReader = new FileReader();
fileReader.onloadend = function(ev) {
promise.asyncSuccess(ev.target.result);
};
fileReader.readAsText(file.files ? file.files[0] : file);
} catch (err) {
promise.asyncError(err);
}
return promise;
}
};
});
Scoped.define("module:Cookies", ["base:Net.Cookies"], function(Cookies) {
return {
get: function(key) {
return Cookies.getCookielikeValue(document.cookie, key);
},
/**
* Will set the Cookie with provided settings
*
* @param {string} key
* @param {string} value
* @param {Date} end
* @param {string} path
* @param {string} domain
* @param {boolean} secure
* @param {'None'|'Lax'|'Strict'} sameSite
*/
set: function(key, value, end, path, domain, secure, sameSite) {
document.cookie = Cookies.createCookielikeValue(key, value, end, path, domain, secure, sameSite);
},
remove: function(key, value, path, domain) {
document.cookie = Cookies.removeCookielikeValue(key, value, path, domain);
},
has: function(key) {
return Cookies.hasCookielikeValue(document.cookie, key);
},
keys: function() {
return Cookies.keysCookielike(document.cookie);
}
};
});
Scoped.define("module:Events", [
"base:Class",
"base:Objs",
"base:Functions",
"module:Dom"
], function(Class, Objs, Functions, Dom, scoped) {
return Class.extend({
scoped: scoped
}, function(inherited) {
return {
constructor: function() {
inherited.constructor.call(this);
this.__callbacks = {};
},
destroy: function() {
this.clear();
inherited.destroy.call(this);
},
on: function(element, events, callback, context, options) {
events.split(" ").forEach(function(event) {
if (!event)
return;
var callback_function = Functions.as_method(callback, context || element);
element.addEventListener(event, callback_function, options && Dom.passiveEventsSupported() ? options : false);
this.__callb