UNPKG

appacitive

Version:

Allows you to integrate applications built using javascript with the Appacitive platform.

1,405 lines (1,195 loc) 316 kB
/* * AppacitiveSDK.js vappacitive-js-sdk-v1.0.11 - Javascript SDK to integrate applications using Appacitive * Copyright (c) 2015 Appacitive Software Pvt Ltd * MIT license : http://www.apache.org/licenses/LICENSE-2.0.html * Project : https://github.com/chiragsanghvi/JavascriptSDK * Contact : support@appacitive.com | csanghvi@appacitive.com * Build time : Mon Dec 12 00:28:43 PST 2016 */ var global = {}; (function() { "use strict"; // create the global object (function() { // create the global object // Export the Appacitive object for **CommonJS**, with backwards-compatibility // for the old `require()` API. If we're not in CommonJS, add `Appacitive` to the // global object. global.Appacitive = { runtime: {} }; if (typeof process !== 'undefined' && !!process.versions && !!process.versions.node) { global.Appacitive.runtime.isNode = true; } else if (typeof window !== 'undefined') { global = window; global.Appacitive = { runtime: { isBrowser: true } }; } })(); var Appacitive = global.Appacitive; Appacitive.initialize = function(options) { options = options || {}; var promise = new Appacitive.Promise(); if (Appacitive.Session.initialized) return promise.fulfill(Appacitive); if (options.masterKey && options.masterKey.length > 0) Appacitive.Session.setMasterKey(options.masterKey); if (!options.apikey || options.apikey.length === 0) { if (options.masterKey) options.apikey = options.masterKey; else throw new Error("apikey is mandatory"); } if (!options.appId || options.appId.length === 0) throw new Error("appId is mandatory"); var _onInitialized = function() { Appacitive.Session.initialized = true; promise.fulfill(Appacitive.User.current()); }; Appacitive.Session.setApiKey(options.apikey); Appacitive.Session.environment(options.env || 'sandbox'); Appacitive.useApiKey = true; Appacitive.appId = options.appId; Appacitive.Session.persistUserToken = options.persistUserToken; if (options.debug) Appacitive.config.debug = true; if (Appacitive.utils._type.isFunction(options.apiLog)) Appacitive.logs.apiLog = options.apiLog; if (Appacitive.utils._type.isFunction(options.apiErrorLog)) Appacitive.logs.apiErrorLog = options.apiErrorLog; if (Appacitive.utils._type.isFunction(options.exceptionLog)) Appacitive.logs.exceptionLog = options.exceptionLog; if (options.userToken) { if (options.expiry == -1) options.expiry = null; else if (!options.expiry) options.expiry = 8450000; Appacitive.Session.setUserAuthHeader(options.userToken, options.expiry); if (options.user) Appacitive.Users.setCurrentUser(options.user); _onInitialized(); } else { if (Appacitive.runtime.isBrowser) { //read usertoken, expiry, expiry-date and user from LocalStorage and set it var keyValues = Appacitive.LocalStorage.multiGet('Appacitive-UserToken','Appacitive-UserTokenExpiry','Appacitive-UserTokenDate','Appacitive-User'); var token = keyValues['Appacitive-UserToken'], expiry = keyValues['Appacitive-UserTokenExpiry'], expiryDate = keyValues['Appacitive-User'], user = keyValues['Appacitive-User']; if (token) { if (!expiry) expiry = -1; if (expiryDate && expiry > 0) { if (new Date(expiryDate + (expiry * 1000)) < new Date()) return; } if (expiry == -1) expiry = null; if (user) Appacitive.Users.setCurrentUser(user, token, expiry); } } _onInitialized(); } return promise; }; })(this); (function(global) { "use strict"; var Appacitive = global.Appacitive; var _XMLHttpRequest = require('xmlhttprequest-with-globalagent').XMLHttpRequest; // base xmlhttprequest class /** * @constructor */ Appacitive._Http = function(request) { if (!request.url) throw new Error("Please specify request url"); if (!request.method) request.method = 'GET'; if (!request.headers) request.headers = []; var data = {}; if (!request.onSuccess || !(typeof request.onSuccess == 'function')) request.onSuccess = function() {}; if (!request.onError || !(typeof request.onError == 'function')) request.onError = function() {}; var promise = Appacitive.Promise.buildPromise({ success: request.onSuccess, error: request.onError }); var doNotStringify = true; request.headers.forEach(function(r) { if (r.key.toLowerCase() == 'content-type') { doNotStringify = true; if (r.value.toLowerCase() == 'application/json' || r.value.toLowerCase() == "application/javascript" || r.value.toLowerCase() == 'application/json; charset=utf-8' || r.value.toLowerCase() == 'application/json; charset=utf-8;') { doNotStringify = false; } } }); if (doNotStringify) data = request.data; else { if (request.data) { data = request.data; if (typeof request.data == 'object') { try { data = JSON.stringify(data); } catch (e) {} } } } var urlDomain = request.url.split('/')[2] || ''; if (global.navigator && (global.navigator.userAgent.indexOf('MSIE 8') != -1) && urlDomain !== window.location.host.toLowerCase()) { request.data = data; var xdr = new _XDomainRequest(request); return xdr; } else { var xhr = new _XMLHttpRequest(); xhr.onreadystatechange = function() { if (this.readyState == 4) { if ((this.status >= 200 && this.status < 300) || this.status == 304) { var response = this.responseText; var contentType = this.getResponseHeader('content-type') || this.getResponseHeader('Content-Type') || ''; if (contentType.toLowerCase() == 'application/json' || contentType.toLowerCase() == 'application/javascript' || contentType.toLowerCase() == 'application/json; charset=utf-8' || contentType.toLowerCase() == 'application/json; charset=utf-8;') { try { var jData = response; if (!Appacitive.runtime.isBrowser) { if (jData[0] != "{") { jData = jData.substr(1, jData.length - 1); } } response = JSON.parse(jData); } catch (e) { return promise.reject(this, new Appacitive.Error(Appacitive.Error.InvalidJson, 'Error while parsing received json ' + response)); } } promise.fulfill(response, this); } else { promise.reject(this, new Appacitive.Error(Appacitive.Error.ConnectionFailed, this.responseText, "Unknown")); } } }; xhr.open(request.method, request.url, request.sync ? false : true); for (var x = 0; x < request.headers.length; x += 1) xhr.setRequestHeader(request.headers[x].key, request.headers[x].value); if (!Appacitive.runtime.isBrowser) xhr.setRequestHeader('User-Agent', 'Appacitive-NodeJSSDK'); xhr.send(data); return promise; } }; })(global); // monolithic file (function(global ) { "use strict"; var Appacitive = global.Appacitive; // httpBuffer class, stores a queue of the requests // and fires them. Global level pre and post processing // goes here. // requires httpTransport class that is able to actually // send the request and receive the response /** * @constructor */ var HttpBuffer = function(httpTransport) { // validate the httpTransport passed // and assign the callback if (!httpTransport || !httpTransport.send || !(typeof httpTransport.send == 'function')) { throw new Error('No applicable httpTransport class found'); } else { httpTransport.onResponse = this.onResponse; } // internal handle to the http requests var _queue = []; // handle to the list of pre-processing functions var _preProcessors = {}, _preCount = 0; // handle to the list of post-processing functions var _postProcessors = {}, _postCount = 0; // public method to add a processor this.addProcessor = function(processor) { if (!processor) return; processor.pre = processor.pre || function() {}; processor.post = processor.post || function() {}; addPreprocessor(processor.pre); addPostprocessor(processor.post); }; // stores a preprocessor // returns a numeric id that can be used to remove this processor var addPreprocessor = function(preprocessor) { _preCount += 1; _preProcessors[_preCount] = preprocessor; return _preCount; }; // removes a preprocessor // returns true if it exists and has been removed successfully // else false var removePreprocessor = function(id) { if (_preProcessors[id]) { delete(_preProcessors[id]); return true; } else { return false; } }; // stores a postprocessor // returns a numeric id that can be used to remove this processor var addPostprocessor = function(postprocessor) { _postCount += 1; _postProcessors[_postCount] = postprocessor; return _postCount; }; // removes a postprocessor // returns true if it exists and has been removed successfully // else false var removePostprocessor = function(id) { if (_postProcessors[id]) { delete(_postProcessors[id]); return true; } else { return false; } }; // enqueues a request in the queue // returns true is succesfully added this.enqueueRequest = function(request) { _queue.push(request); }; this.changeRequestForCors = function(request) { var body = { m: request.method.toUpperCase() }; request.headers.forEach(function(h) { body[h.key] = h.value; }); request.prevHeaders = request.headers; request.headers = []; request.headers.push({ key: 'Content-Type', value: 'text/plain; charset=utf-8' }); request.method = 'POST'; if (request.data) body.b = request.data; delete request.data; if (Appacitive.config.debug) { if (request.url.indexOf('?') === -1) request.url = request.url + '?debug=true'; else request.url = request.url + '&debug=true'; } if (Appacitive.config.metadata) { if (request.url.indexOf('?') === -1) request.url = request.url + '?metadata=true'; else request.url = request.url + '&metadata=true'; } try { request.data = JSON.stringify(body); } catch (e) {} return request; }; // notifies the queue that there are requests pending // this will start firing the requests via the method // passed while initalizing this.notify = function() { if (_queue.length === 0) return; // for convienience, extract the postprocessing object into an array var _callbacks = []; for (var processor in _postProcessors) { if (_postProcessors.hasOwnProperty(processor)) { _callbacks.push(_postProcessors[processor]); } } while (_queue.length > 0) { var toFire = _queue.shift(); // execute the preprocessors // if they return anything, pass it along // to be able to access it in the post processing callbacks var _state = []; for (var processor in _preProcessors) { if (_preProcessors.hasOwnProperty(processor)) { _state.push(_preProcessors[processor](toFire)); } } this.changeRequestForCors(toFire); // send the requests // and the callbacks and the // results returned from the preprocessors httpTransport.send(toFire, _callbacks, _state); } }; // callback to be invoked when a request has completed this.onResponse = function(responseData) { console.dir(responseData); }; }; // base httpTransport class /** * @constructor */ var _HttpTransport = function() { var _notImplemented = function() { throw new Error('Not Implemented Exception'); }; var _notProvided = function() { throw new Error('Delegate not provided'); }; // implements this this.send = _notImplemented; this.inOnline = _notImplemented; // needs these callbacks to be set this.onResponse = function(response, request) { _notImplemented(); }; this.onError = function(request) { _notImplemented(); }; }; // httpRequest class, encapsulates the request // without bothering about how it is going to be fired. /** * @constructor */ var HttpRequest = function(o) { o = o || {}; this.url = o.url || ''; this.data = o.data || {}; this.headers = o.headers || []; this.method = o.method || 'GET'; this.onSuccess = o.onSuccess || function() {}; this.onError = o.onError || function() {}; this.send = function(doNotStringify) { return new Appacitive._Http(this, doNotStringify); }; }; // browser based http transport class /** * @constructor */ var BasicHttpTransport = function() { var _super = new _HttpTransport(); _super.isOnline = function() { return true; }; var _executeCallbacks = function(response, callbacks, states) { if (callbacks.length != states.length) { throw new Error('Callback length and state length mismatch!'); } for (var x = 0; x < callbacks.length; x += 1) { callbacks[x].apply({}, [response, states[x]]); } }; var that = _super; var _trigger = function(request, callbacks, states) { request.options = request.options || {}; new Appacitive._Http({ method: request.method, url: request.url, headers: request.headers, data: request.data, sync: request.options.sync, onSuccess: function(data, xhr) { if (!data) { that.onError(request, { responseText: { code: '400', message: 'Invalid request' } }); return; } try { data = JSON.parse(data); } catch (e) {} // execute the callbacks first _executeCallbacks(data, callbacks, states); if ((data.code >= 200 && data.code <= 300) || (data.status && data.status.code >= 200 && data.status.code <= 300)) { that.onResponse(request, data); } else { data = data || {}; data = data.status || data; data.message = data.message || 'Bad Request'; data.code = data.code || '400'; that.onError(request, { responseText: data }); } }, onError: function(xhr, error) { var data = {}; if (error) { data = Appacitive.Error.toJSON(error); } else { data.message = xhr.responseData || xhr.responseText || 'Bad Request'; data.code = xhr.status || '400'; } that.onError(request, { responseText: data }); } }); }; _super.send = function(request, callbacks, states) { if (!Appacitive.Session.initialized) throw new Error("Initialize Appacitive SDK"); if (typeof request.beforeSend == 'function') { request.beforeSend(request); } _trigger(request, callbacks, states); }; return _super; }; // http functionality provider /** * @constructor */ var HttpProvider = function() { // actual http provider //var _inner = Appacitive.runtime.isBrowser ? new JQueryHttpTransport() : new NodeHttpTransport(); var _inner = new BasicHttpTransport(); // the http buffer var _buffer = new HttpBuffer(_inner); // used to pause/unpause the provider var _paused = false; // allow pausing/unpausing this.pause = function() { _paused = true; }; this.unpause = function() { _paused = false; }; // allow adding processors to the buffer this.addProcessor = function(processor) { var _processorError = new Error('Must provide a processor object with either a "pre" function or a "post" function.'); if (!processor) throw _processorError; if (!processor.pre && !processor.post) throw _processorError; _buffer.addProcessor(processor); }; // the method used to send the requests this.send = function(request) { request.promise = (Appacitive.Promise.is(request.promise)) ? request.promise : new Appacitive.Promise.buildPromise({ error: request.onError }); _buffer.enqueueRequest(request); // notify the queue if the actual transport // is ready to send the requests if (_inner.isOnline() && _paused === false) { _buffer.notify(); } return request.promise; }; // method used to clear the queue this.flush = function(force) { if (!force) { if (_inner.isOnline()) { _buffer.notify(); } } else { _buffer.notify(); } }; // the error handler this.onError = function(request, response) { var error = response.responseText; Appacitive.logs.logRequest(request, error, error, 'error'); if (request.entity && request.entity._triggerError) request.entity._triggerError(request.options, new Appacitive.Error(error)); request.promise.reject(new Appacitive.Error(error), request.entity); }; _inner.onError = this.onError; // the success handler this.onResponse = function(request, response) { if (request.onSuccess) { if (request.context) { request.onSuccess.apply(request.context, [response]); } else { request.onSuccess(response); } } Appacitive.logs.logRequest(request, response, response ? response.status : null, 'successful'); }; _inner.onResponse = this.onResponse; }; // create the http provider and the request Appacitive.http = new HttpProvider(); Appacitive.HttpRequest = HttpRequest; /* PLUGIN: Http Utilities */ // compulsory plugin // handles session and shits (function(global) { var Appacitive = global.Appacitive; if (!Appacitive) return; if (!Appacitive.http) return; Appacitive.http.addProcessor({ pre: function(request) { return request; }, post: function(response, request) { try { var _valid = Appacitive.Session.isSessionValid(response); if (!_valid.status) { if (_valid.isSession) { if (Appacitive.Session.get() !== null) { Appacitive.Session.resetSession(); } Appacitive.http.send(request); } } else { if (response && ((response.status && response.status.code && (response.status.code == '19036' || response.status.code == '421')) || (response.code && (response.code == '19036' || response.code == '421')))) { Appacitive.Users.logout(); } else { Appacitive.Session.incrementExpiry(); } } } catch (e) {} } }); Appacitive.http.addProcessor({ pre: function(req) { return { start: new Date().getTime(), request: req }; }, post: function(response, args) { args.request.timeTakenInMilliseconds = new Date().getTime() - args.start; } }); })(global); /* Http Utilities */ })(global); var _type = function(o) { // handle null in old IE if (o === null) { return 'null'; } if (typeof o === 'undefined' || o === 'undefined') { return 'undefined'; } // handle DOM elements if (o && (o.nodeType === 1 || o.nodeType === 9)) { return 'element'; } var s = Object.prototype.toString.call(o); var type = s.match(/\[object (.*?)\]/)[1].toLowerCase(); // handle NaN and Infinity if (type === 'number') { if (isNaN(o)) { return 'nan'; } if (!isFinite(o)) { return 'infinity'; } } return type; }; (function(global) { "use strict"; // Add ECMA262-5 method binding if not supported natively // if (!('bind' in Function.prototype)) { Function.prototype.bind = function(owner) { var that = this; if (arguments.length <= 1) { return function() { return that.apply(owner, arguments); }; } else { var args = Array.prototype.slice.call(arguments, 1); return function() { return that.apply(owner, arguments.length === 0 ? args : args.concat(Array.prototype.slice.call(arguments))); }; } }; } // Add ECMA262-5 string trim if not supported natively // if (!('trim' in String.prototype)) { String.prototype.trim = function() { return this.replace(/^\s+/, '').replace(/\s+$/, ''); }; } // Add ECMA262-5 Array methods if not supported natively // if (!('indexOf' in Array.prototype)) { Array.prototype.indexOf = function(find, i /*opt*/ ) { if (i === undefined) i = 0; if (i < 0) i += this.length; if (i < 0) i = 0; for (var n = this.length; i < n; i++) if (i in this && this[i] === find) return i; return -1; }; } if (!('lastIndexOf' in Array.prototype)) { Array.prototype.lastIndexOf = function(find, i /*opt*/ ) { if (i === undefined) i = this.length - 1; if (i < 0) i += this.length; if (i > this.length - 1) i = this.length - 1; for (i++; i-- > 0;) /* i++ because from-argument is sadly inclusive */ if (i in this && this[i] === find) return i; return -1; }; } if (!('forEach' in Array.prototype)) { Array.prototype.forEach = function(action, that /*opt*/ ) { for (var i = 0, n = this.length; i < n; i++) if (i in this) action.call(that, this[i], i, this); }; } if (!('map' in Array.prototype)) { Array.prototype.map = function(mapper, that /*opt*/ ) { var other = new Array(this.length); for (var i = 0, n = this.length; i < n; i++) if (i in this) other[i] = mapper.call(that, this[i], i, this); return other; }; } if (!('filter' in Array.prototype)) { Array.prototype.filter = function(filter, that /*opt*/ ) { var other = [], v; for (var i = 0, n = this.length; i < n; i++) if (i in this && filter.call(that, v = this[i], i, this)) other.push(v); return other; }; } if (!('every' in Array.prototype)) { Array.prototype.every = function(tester, that /*opt*/ ) { for (var i = 0, n = this.length; i < n; i++) if (i in this && !tester.call(that, this[i], i, this)) return false; return true; }; } if (!('some' in Array.prototype)) { Array.prototype.some = function(tester, that /*opt*/ ) { for (var i = 0, n = this.length; i < n; i++) if (i in this && tester.call(that, this[i], i, this)) return true; return false; }; } if (!('find' in Array.prototype)) { Array.prototype.find = function(mapper, that /*opt*/ ) { var list = this; var length = list.length; if (length === 0) return undefined; for (var i = 0, value; i < length && i in list; i++) { value = list[i]; if (mapper.call(that, value, i, list)) return value; } return undefined; }; } if (!('where' in Array.prototype)) { Array.prototype.where = function(attrs, first /*opt*/ ) { var list = this; var length = list.length; if (length === 0) return undefined; if (Object.isEmpty(attrs)) return first ? void 0 : []; return list[first ? 'find' : 'filter'](function(obj) { for (var key in attrs) { if (attrs[key] !== obj[key]) return false; } return true; }); }; Array.prototype.findWhere = function(attrs) { return this.where(attrs, true); }; } if (!('each' in Array.prototype)) { Array.prototype.each = function(callback, that) { for (var i = 0; i < this.length; i++) { callback.apply(that, [this[i]]); } }; } if (!('difference' in Array.prototype)) { Array.prototype.difference = function(a) { return this.filter(function(i) { return a.indexOf(i) < 0; }); }; } if (!('without' in Array.prototype)) { Array.prototype.without = function() { return this.difference(Array.prototype.slice.call(arguments, 0)); }; } if ('function' !== typeof Array.prototype.reduce) { Array.prototype.reduce = function(callback /*, initialValue*/ ) { 'use strict'; if (null === this || 'undefined' === typeof this) { throw new TypeError('Array.prototype.reduce called on null or undefined'); } if ('function' !== typeof callback) { throw new TypeError(callback + ' is not a function'); } var t = Object(this), len = t.length >>> 0, k = 0, value; if (arguments.length >= 2) { value = arguments[1]; } else { while (k < len && !k in t) k++; if (k >= len) throw new TypeError('Reduce of empty array with no initial value'); value = t[k++]; } for (; k < len; k++) { if (k in t) { value = callback(value, t[k], k, t); } } return value; }; } var _lookupIterator = function(value, context) { if (value == null) return _.identity; if (!_.isFunction(value)) return function(obj) { return obj[value]; }; if (!context) return value; return function() { return value.apply(context, arguments); }; }; Array.prototype.pluck = function(property) { var results = []; this.each(function(value) { results.push(value[property]); }); return results; }; Array.prototype.sortBy = function(iterator, context) { iterator = _lookupIterator(iterator, context); return this.map(function(value, index) { return { value: value, criteria: iterator.call(context, value, index, this) }; }, this).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }; Array.prototype.removeAll = function(obj) { // Return null if no objects were found and removed var destroyed = null; for (var i = 0; i < this.length; i++) { // Use while-loop to find adjacent equal objects while (this[i] === obj) { // Remove this[i] and store it within destroyed destroyed = this.splice(i, 1)[0]; } } return destroyed; }; // attach the .compare method to Array's prototype to call it on any array Array.prototype.compare = function(array) { // if the other array is a falsy value, return if (!array) return false; // compare lengths - can save a lot of time if (this.length != array.length) return false; for (var i = 0, l = this.length; i < l; i++) { // Check if we have nested arrays if (this[i] instanceof Array && array[i] instanceof Array) { // recurse into the nested arrays if (!this[i].compare(array[i])) return false; } else if (this[i] != array[i]) { // Warning - two different object instances will never be equal: {x:20} != {x:20} return false; } } return true; }; // attach the .equals method to Array's prototype to call it on any array Array.prototype.equals = function(array, strict) { // if the other array is a falsy value, return if (!array) return false; // set strict mode as false if (arguments.length == 1) strict = false; // compare lengths - can save a lot of time if (this.length != array.length) return false; for (var i = 0; i < this.length; i++) { // Check if we have nested arrays if (this[i] instanceof Array && array[i] instanceof Array) { if (!this[i].equals(array[i], strict)) return false; } else if (strict && !_type.isEqual(this[i], array[i])) { // Warning - two different object instances will never be equal: {x:20} != {x:20} return false; } else if (!strict) { return this.sort().equals(array.sort(), true); } } return true; }; // Override only if native toISOString is not defined if (!Date.prototype.toISOString) { (function() { function pad(number) { var r = String(number); if (r.length === 1) { r = '0' + r; } return r; } Date.prototype.toISOString = function() { return this.getUTCFullYear() + '-' + pad(this.getUTCMonth() + 1) + '-' + pad(this.getUTCDate()) + 'T' + pad(this.getUTCHours()) + ':' + pad(this.getUTCMinutes()) + ':' + pad(this.getUTCSeconds()) + '.' + String((this.getUTCMilliseconds() / 1000).toFixed(3)).slice(2, 5) + 'Z'; }; }()); }; String.addSlashes = function(str) { if (!str) return str; str = str.replace(/\\/g, '\\\\'); str = str.replace(/\'/g, '\\\''); str = str.replace(/\"/g, '\\"'); str = str.replace(/\0/g, '\\0'); return str; }; String.stripSlashes = function(str) { if (!str) return str; str = str.replace(/\\'/g, '\''); str = str.replace(/\\"/g, '"'); str = str.replace(/\\0/g, '\0'); str = str.replace(/\\\\/g, '\\'); return str; }; if (typeof console === 'undefined' || console === null) { console = { log: function() {}, dir: function() {} }; } var types = [ 'Null', 'Undefined', 'Object', 'Array', 'String', 'Number', 'Boolean', 'Function', 'RegExp', 'Element', 'NaN', 'Infinite' ]; var generateMethod = function(t) { _type['is' + t] = function(o) { return _type(o) === t.toLowerCase(); }; }; for (var i = 0; i < types.length; i++) { generateMethod(types[i]); } _type['isNullOrUndefined'] = function(o) { return _type(o) == 'null' || _type(o) == 'undefined'; }; _type['isNumeric'] = function(n) { return !isNaN(parseFloat(n)) && isFinite(n); }; _type['isDate'] = function(n) { return n instanceof Date; }; // Internal recursive comparison function for `isEqual`. var eq = function(a, b, aStack, bStack) { var toString = Object.prototype.toString; var _has = function(obj, key) { return Object.prototype.hasOwnProperty.call(obj, key); } // Identical objects are equal. `0 === -0`, but they aren't identical. // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). if (a === b) return a !== 0 || 1 / a == 1 / b; // A strict comparison is necessary because `null == undefined`. if (a == null || b == null) return a === b; // Compare `[[Class]]` names. var className = toString.call(a); if (className != toString.call(b)) return false; switch (className) { // Strings, numbers, dates, and booleans are compared by value. case '[object String]': // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is // equivalent to `new String("5")`. return a == String(b); case '[object Number]': // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for // other numeric values. return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); case '[object Date]': case '[object Boolean]': // Coerce dates and booleans to numeric primitive values. Dates are compared by their // millisecond representations. Note that invalid dates with millisecond representations // of `NaN` are not equivalent. return +a == +b; } if (typeof a != 'object' || typeof b != 'object') return false; if (a instanceof global.Appacitive.GeoCoord && b instanceof global.Appacitive.GeoCoord) return (a.toString() == b.toString()); // Assume equality for cyclic structures. The algorithm for detecting cyclic // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. var length = aStack.length; while (length--) { // Linear search. Performance is inversely proportional to the number of // unique nested structures. if (aStack[length] == a) return bStack[length] == b; } // Objects with different constructors are not equivalent, but `Object`s // from different frames are. var aCtor = a.constructor, bCtor = b.constructor; if (aCtor !== bCtor && !(_types.isFunction(aCtor) && (aCtor instanceof aCtor) && _types.isFunction(bCtor) && (bCtor instanceof bCtor)) && ('constructor' in a && 'constructor' in b)) { return false; } // Add the first object to the stack of traversed objects. aStack.push(a); bStack.push(b); var size = 0, result = true; // Recursively compare objects and arrays. if (className == '[object Array]') { // Compare array lengths to determine if a deep comparison is necessary. size = a.length; result = size == b.length; if (result) { // Deep compare the contents, ignoring non-numeric properties. while (size--) { if (!(result = eq(a[size], b[size], aStack, bStack))) break; } } } else { // Deep compare objects. for (var key in a) { if (_has(a, key)) { // Count the expected number of properties. size++; // Deep compare each member. if (!(result = _has(b, key) && eq(a[key], b[key], aStack, bStack))) break; } } // Ensure that both objects contain the same number of properties. if (result) { for (key in b) { if (_has(b, key) && !(size--)) break; } result = !size; } } // Remove the first object from the stack of traversed objects. aStack.pop(); bStack.pop(); return result; }; // Perform a deep comparison to check if two objects are equal. _type.isEqual = function(a, b) { return eq(a, b, [], []); }; global.Appacitive.utils = global.Appacitive.utils || {}; global.Appacitive.utils._type = _type; })(global); (function(global) { "use strict"; var ArrayProto = Array.prototype; var ObjectProto = Object.prototype; var Appacitive = global.Appacitive; Appacitive.utils._each = function(obj, iterator, context) { if (obj == null) return; if (ArrayProto.forEach && obj.forEach === ArrayProto.forEach) { obj.forEach(iterator, context); } else if (obj.length === +obj.length) { for (var i = 0, l = obj.length; i < l; i++) { if (iterator.call(context, obj[i], i, obj) === {}) return; } } else { for (var key in obj) { if (ObjectProto.hasOwnProperty.call(obj, key)) { if (iterator.call(context, obj[key], key, obj) === {}) return; } } } }; // Extend a given object with all the properties in passed-in object(s). Appacitive.utils._extend = function(obj) { Appacitive.utils._each(ArrayProto.slice.call(arguments, 1), function(source) { if (source) { for (var prop in source) { obj[prop] = source[prop]; } } }); return obj; }; Appacitive.utils._reject = function(col, fn) { return col.filter(function(v) { return !fn(v); }); }; // Deep Extend a given object with all the properties in passed-in object(s). Appacitive.utils._deepExtend = function(obj) { var slice = Array.prototype.slice; Appacitive.utils._each(slice.call(arguments, 1), function(source) { for (var prop in source) { if (Appacitive.utils._type.isArray(source[prop])) { if (!Appacitive.utils._type.isArray(obj[prop])) obj[prop] = []; obj[prop] = Appacitive.utils._reject(Appacitive.utils._extend(obj[prop], source[prop]), function(item) { return Appacitive.utils._type.isNull(item); }); } else if (Appacitive.utils._type.isObject(source[prop]) && (!(source[prop] instanceof Appacitive.Object)) && (!(source[prop] instanceof Appacitive.Connection)) && (!(source[prop] instanceof Appacitive.GeoCoord))) { if (!Appacitive.utils._type.isObject(obj[prop])) { obj[prop] = {}; } obj[prop] = Appacitive.utils._extend(obj[prop], source[prop]); } else { obj[prop] = source[prop]; } } }); return obj; }; // Helper function to correctly set up the prototype chain, for subclasses. // Similar to `goog.inherits`, but uses a hash of prototype properties and // class properties to be extended. var extend = function(protoProps, staticProps) { var parent = this; var child; // The constructor function for the new subclass is either defined by you // (the "constructor" property in your `extend` definition), or defaulted // by us to simply call the parent's constructor. if (Appacitive.utils._type.isObject(protoProps) && protoProps.hasOwnProperty('constructor')) { child = protoProps.constructor; } else { child = function() { return parent.apply(this, arguments); }; } // Add static properties to the constructor function, if supplied. Appacitive.utils._extend(child, parent, staticProps); // Set the prototype chain to inherit from `parent`, without calling // `parent`'s constructor function. var Surrogate = function() { this.constructor = child; }; Surrogate.prototype = parent.prototype; child.prototype = new Surrogate; // Add prototype properties (instance properties) to the subclass, // if supplied. if (protoProps) Appacitive.utils._extend(child.prototype, protoProps); // Set a convenience property in case the parent's prototype is needed // later. child.__super__ = parent.prototype; return child; }; Appacitive.utils.classExtend = function(parent, protoProps, staticProps) { return extend.apply(parent, [protoProps, staticProps]); }; Appacitive.utils._result = function(object, property, fallback) { var value = object == null ? void 0 : object[property]; if (value === void 0) { value = fallback; } return Appacitive.utils._type.isFunction(value) ? value.call(object) : value; }; Appacitive.clone = Appacitive.utils._clone = function(obj) { if (!Appacitive.utils._type.isObject(obj)) return obj; return Appacitive.utils._type.isArray(obj) ? obj.slice() : Appacitive.utils._extend({}, obj); }; })(global); (function(global) { "use strict"; var Appacitive = global.Appacitive; var _type = Appacitive.utils._type; var _extend = Appacitive.utils._extend; var _deepExtend = Appacitive.utils._deepExtend; Appacitive.logs = {}; var invoke = function(callback, log) { setTimeout(function() { try { callback.call({}, log); } catch (e) {} }, 0); }; Appacitive.logs.logRequest = function(request, response, status, type) { response = response || {}; status = status || {}; var body = {}; try { body = JSON.parse(request.data); if (!_type.isObject(body)) body = {}; } catch (e) {} var log = { status: type, referenceId: status.referenceid, date: new Date().toISOString(), method: body['m'], url: decodeURIComponent(request.url), responseTime: request.timeTakenInMilliseconds, headers: {}, request: null, response: response, description: request.description }; if (request.headers) { request.headers.forEach(function(h) { log.headers[h.key] = h.value; }); } if (request.prevHeaders) { request.prevHeaders.forEach(function(h) { log.headers[h.key] = h.value; }); } if (log.method !== 'GET') { log.request = body['b']; } if (type == 'error') { if (Appacitive.runtime.isBrowser) console.dir(log); if (_type.isFunction(Appacitive.logs.apiErrorLog)) { invoke(Appacitive.logs.apiErrorLog, log); } } if (_type.isFunction(Appacitive.logs.apiLog)) { invoke(Appacitive.logs.apiLog, log); } }; Appacitive.logs.logException = function(error) { if (_type.isFunction(Appacitive.logs.exceptionLog)) { invoke(Appacitive.logs.exceptionLog, error); } }; })(global); (function(global) { "use strict"; var Appacitive = global.Appacitive; var _type = Appacitive.utils._type; var _extend = Appacitive.utils._extend; var _deepExtend = Appacitive.utils._deepExtend; /** * @param {...string} var_args */ String.format = function(text, var_args) { if (arguments.length <= 1) { return text; } var tokenCount = arguments.length - 2; for (var token = 0; token <= tokenCount; token++) { //iterate through the tokens and replace their placeholders from the original text in order text = text.replace(new RegExp("\\{" + token + "\\}", "gi"), arguments[token + 1]); } return text; }; String.prototype.toPascalCase = function() { return this.charAt(0).toUpperCase() + this.slice(1); }; String.prototype.trimChar = function(char1) { var pattern = new RegExp("^" + char1); var returnStr = this; if (pattern.test(returnStr)) returnStr = returnStr.slice(1, returnStr.length); pattern = new RegExp(char1 + "$"); if (pattern.test(returnStr)) returnStr = returnStr.slice(0, -1); return returnStr; }; String.toSearchString = function(text) { if (typeof(text) === 'undefined') text = ''; var result = ''; for (var x = 0; x < text.length; x = x + 1) { if (' .,;#'.indexOf(text[x]) === -1) result += text[x]; } result = result.toLowerCase(); return result; }; String.contains = function(s1, s2) {