appacitive
Version:
Allows you to integrate applications built using javascript with the Appacitive platform.
1,405 lines (1,195 loc) • 316 kB
JavaScript
/*
* 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) {