UNPKG

betajs-browser

Version:

BetaJS-Browser is a client-side JavaScript framework for Browser-specific methods.

1,642 lines (1,466 loc) 182 kB
/*! betajs-browser - v1.0.140 - 2023-08-30 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.140 - 2023-08-30 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.140", "datetime": 1693425262199 }; }); 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:Canvas", [ "base:Maths" ], function(Maths) { return { isCanvasBlack: function(canvas) { if (!canvas) throw Error("Missing canvas"); var data = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height).data; if (!data) return; var MAX_SAMPLE_SIZE = 10000; var sum = 0; var count = 0; if (canvas.width * canvas.height * 3 / 4 < MAX_SAMPLE_SIZE) { // sample all pixels sum = data.reduce(function(s, v, i) { if (i && (i + 1) % 4 !== 0) { s += v; count++; } return s; }); return sum / count < 10; } else { // random sampling count = MAX_SAMPLE_SIZE; for (var n = 0; n < MAX_SAMPLE_SIZE; n++) { var i = Maths.randomInt(0, data.length); while (i && (i + 1) % 4 === 0) i = Maths.randomInt(0, data.length); sum += data[i]; } } return sum / count < 10; }, isImageBlack: function(image) { if (!image) throw Error("Missing image"); var canvas = document.createElement("canvas"); canvas.width = image.width; canvas.height = image.height; canvas.getContext('2d').drawImage(image, 0, 0, canvas.width, canvas.height); return this.isCanvasBlack(canvas); } }; }); 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