diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9845fd22..de2f98d3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,9 @@
## Unreleased
-* Add support for logging events to multiple Amplitude apps. **Note this is a major update, and may break backwards compatability.** See [Readme](https://github.com/amplitude/Amplitude-Javascript#300-update-and-logging-events-to-multiple-amplitude-apps) for details.
* Fix bug where saveReferrer throws exception if sessionStorage is disabled.
* Log messages with a try/catch to support IE 8.
* Validate event properties during logEvent and initialization before sending request.
* Add instructions for proper integration with RequireJS.
-* Init callback now passes the Amplitude instance as an argument to the callback function.
## 2.9.0 (January 15, 2016)
diff --git a/README.md b/README.md
index a848d855..cb4454e2 100644
--- a/README.md
+++ b/README.md
@@ -9,15 +9,15 @@ Amplitude-Javascript
```html
@@ -29,83 +29,11 @@ Amplitude-Javascript
4. To track an event anywhere on the page, call:
```javascript
- amplitude.getInstance().logEvent('EVENT_IDENTIFIER_HERE');
+ amplitude.logEvent('EVENT_IDENTIFIER_HERE');
```
5. Events are uploaded immediately and saved to the browser's local storage until the server confirms the upload. After calling logEvent in your app, you will immediately see data appear on Amplitude.
-# 3.0.0 Update and Logging Events to Multiple Amplitude Apps #
-
-Version 3.0.0 is a major update that brings support for logging events to multiple Amplitude apps (multiple API keys). **Note: this change is not 100% backwards compatible and may break on your setup.** See the subsection below on backwards compatibility.
-
-### API Changes and Backwards Compatibility ###
-
-The `amplitude` object now maintains one or more instances, where each instance has separate apiKey, userId, deviceId, and settings. Having separate instances allows for the logging of events to separate Amplitude apps.
-
-The most important API change is how you interact with the `amplitude` object. Before v3.0.0, you would directly call `amplitude.logEvent('EVENT_NAME')`. Now the preferred way is to call functions on an instance as follows: `amplitude.getInstance('INSTANCE_NAME').logEvent('EVENT_NAME')` This notation will be familiar to people who have used our iOS and Android SDKs.
-
-Most people upgrading to v3.0.0 will continue logging events to a single Amplitude app. To make this transition as smooth as possible, we try to maintain backwards compatibility for most things by having a `default instance`, which you can fetch by calling `amplitude.getInstance()` with no instance name. The code examples in this README have been updated to follow this use case. All of the existing event data, existing settings, and returning users (users who already have a deviceId and/or userId) will stay with the `default instance`. You should initialize the default instance with your existing apiKey.
-
-All of the *public* methods of `amplitude` should still work as expected, as they have all been mapped to their equivalent on the default instance.
-
-For example `amplitude.init('API_KEY')` should still work as it has been mapped to `amplitude.getInstance().init('API_KEY')`.
-
-Likewise `amplitude.logEvent('EVENT_NAME')` should still work as it has been mapped to `amplitude.getInstance().logEvent('EVENT_NAME')`.
-
-`amplitude.options` will still work and will map to `amplitude.getInstance().options`, if for example you were using it to access the deviceId.
-
-**Things that will break:** if you were accessing private properties on the `amplitude` object, those will no longer work, e.g. `amplitude._sessionId`, `amplitude._eventId`, etc. You will need to update those references to fetch from the default instance like so: `amplitude.getInstance()._sessionId` and `amplitude.getInstance()._eventId`, etc.
-
-### Logging Events to a Single Amplitude App / API Key (Preferred Method) ###
-
-If you want to continue logging events to a single Amplitude App (and a single API key), then you should call functions on the `default instance`, which you can fetch by calling `amplitude.getInstance()` with no instance name. Here is an example:
-
-```javascript
-amplitude.getInstance().init('API_KEY');
-amplitude.getInstance().logEvent('EVENT_NAME');
-```
-
-You can also assign instances to a variable and call functions on that variable like so:
-
-```javascript
-var app = amplitude.getInstance();
-app.init('API_KEY');
-app.logEvent('EVENT_NAME');
-```
-
-### Logging Events to Multiple Amplitude Apps ###
-
-If you want to log events to multiple Amplitude apps, you will need to have separate instances for each Amplitude app. As mentioned earlier, each instance will allow for completely independent apiKeys, userIds, deviceIds, and settings.
-
-You need to assign a name to each Amplitude app / instance, and use that name consistently when fetching that instance to call functions. **IMPORTANT: Once you have chosen a name for that instance you cannot change it.** Every instance's data and settings are tied to its name, and you will need to continue using that instance name for all future versions of your app to maintain data continuity, so chose your instance names wisely. Note these names do not need to be the names of your apps in the Amplitude dashboards, but they need to remain consistent throughout your code. You also need to be sure that each instance is initialized with the correct apiKey.
-
-Instance names must be nonnull and nonempty strings. Names are case-insensitive. You can fetch each instance by name by calling `amplitude.getInstance('INSTANCE_NAME')`.
-
-As mentioned before, each new instance created will have its own apiKey, userId, deviceId, and settings. **You will have to reconfigure all the settings for each instance.** This gives you the freedom to have different settings for each instance.
-
-### Example of how to Set Up and Log Events to Two Separate Apps ###
-```javascript
-amplitude.getInstance().init('12345', null, {batchEvents: true}); // existing app, existing settings, and existing API key
-amplitude.getInstance('new_app').init('67890', null, {includeReferrer: true}); // new app, new API key
-
-amplitude.getInstance('new_app').setUserId('joe@gmail.com'); // need to reconfigure new app
-amplitude.getInstance('new_app').setUserProperties({'gender':'male'});
-amplitude.getInstance('new_app').logEvent('Clicked');
-
-var identify = new amplitude.Identify().add('karma', 1);
-amplitude.getInstance().identify(identify);
-amplitude.getInstance().logEvent('Viewed Home Page');
-```
-
-### Synchronizing Device Ids Between Apps ###
-
-As mentioned before, each instance will have its own deviceId. If you want your apps to share the same deviceId, you can do so *after init* via the `getDeviceId` and `setDeviceId` methods. Here's an example of how to copy the existing deviceId to the `new_app` instance:
-
-```javascript
-var deviceId = amplitude.getInstance().getDeviceId(); // existing deviceId
-amplitude.getInstance('new_app').setDeviceId(deviceId); // transferring existing deviceId to new_app
-```
-
# Tracking Events #
It's important to think about what types of events you care about as a developer. You should aim to track between 20 and 200 types of events on your site. Common event types are actions the user initiates (such as pressing a button) and events you want the user to complete (such as filling out a form, completing a level, or making a payment). Here is our help article on [Event Taxonomy and Best Practices](https://amplitude.zendesk.com/hc/en-us/articles/211988918-How-to-Approach-Your-Event-Taxonomy).
@@ -115,19 +43,19 @@ It's important to think about what types of events you care about as a developer
If your app has its own login system that you want to track users with, you can call `setUserId` at any time:
```javascript
-amplitude.getInstance().setUserId('USER_ID_HERE');
+amplitude.setUserId('USER_ID_HERE');
```
A user's data will be merged on the backend so that any events up to that point from the same browser will be tracked under the same user. Note: if a user logs out, or you want to log the events under an anonymous user, you may set the userId to `null` like so:
```javascript
-amplitude.getInstance().setUserId(null); // not string 'null'
+amplitude.setUserId(null); // not string 'null'
```
You can also add the user ID as an argument to the `init` call:
```javascript
-amplitude.getInstance().init('YOUR_API_KEY_HERE', 'USER_ID_HERE');
+amplitude.init('YOUR_API_KEY_HERE', 'USER_ID_HERE');
```
# Setting Event Properties #
@@ -137,7 +65,7 @@ You can attach additional data to any event by passing a Javascript object as th
```javascript
var eventProperties = {};
eventProperties.key = 'value';
-amplitude.getInstance().logEvent('EVENT_IDENTIFIER_HERE', eventProperties);
+amplitude.logEvent('EVENT_IDENTIFIER_HERE', eventProperties);
```
Alternatively, you can set multiple event properties like this:
@@ -147,7 +75,7 @@ var eventProperties = {
'age': 20,
'key': 'value'
};
-amplitude.getInstance().logEvent('EVENT_IDENTIFIER_HERE', eventProperties);
+amplitude.logEvent('EVENT_IDENTIFIER_HERE', eventProperties);
```
# User Properties and User Property Operations #
@@ -158,38 +86,38 @@ The SDK supports the operations `set`, `setOnce`, `unset`, and `add` on individu
```javascript
var identify = new amplitude.Identify().set('gender', 'female').set('age', 20);
- amplitude.getInstance().identify(identify);
+ amplitude.identify(identify);
```
2. `setOnce`: this sets the value of a user property only once. Subsequent `setOnce` operations on that user property will be ignored. In the following example, `sign_up_date` will be set once to `08/24/2015`, and the following setOnce to `09/14/2015` will be ignored:
```javascript
var identify = new amplitude.Identify().setOnce('sign_up_date', '08/24/2015');
- amplitude.getInstance().identify(identify);
+ amplitude.identify(identify);
var identify = new amplitude.Identify().setOnce('sign_up_date', '09/14/2015');
- amplitude.getInstance().identify(identify);
+ amplitude.identify(identify);
```
3. `unset`: this will unset and remove a user property.
```javascript
var identify = new amplitude.Identify().unset('gender').unset('age');
- amplitude.getInstance().identify(identify);
+ amplitude.identify(identify);
```
4. `add`: this will increment a user property by some numerical value. If the user property does not have a value set yet, it will be initialized to 0 before being incremented.
```javascript
var identify = new amplitude.Identify().add('karma', 1).add('friends', 1);
- amplitude.getInstance().identify(identify);
+ amplitude.identify(identify);
```
5. `append`: this will append a value or values to a user property. If the user property does not have a value set yet, it will be initialized to an empty list before the new values are appended. If the user property has an existing value and it is not a list, it will be converted into a list with the new value appended.
```javascript
var identify = new amplitude.Identify().append('ab-tests', 'new-user-test').append('some_list', [1, 2, 3, 4, 'values']);
- amplitude.getInstance().identify(identify);
+ amplitude.identify(identify);
```
Note: if a user property is used in multiple operations on the same `Identify` object, only the first operation will be saved, and the rest will be ignored. In this example, only the set operation will be saved, and the add and unset will be ignored:
@@ -199,7 +127,7 @@ var identify = new amplitude.Identify()
.set('karma', 10)
.add('karma', 1)
.unset('karma');
-amplitude.getInstance().identify(identify);
+amplitude.identify(identify);
```
### Arrays in User Properties ###
@@ -211,7 +139,7 @@ var identify = new amplitude.Identify()
.set('colors', ['rose', 'gold'])
.append('ab-tests', 'campaign_a')
.append('existing_list', [4, 5]);
-amplitude.getInstance().identify(identify);
+amplitude.identify(identify);
```
### Setting Multiple Properties with `setUserProperties` ###
@@ -223,7 +151,7 @@ var userProperties = {
gender: 'female',
age: 20
};
-amplitude.getInstance().setUserProperties(userProperties);
+amplitude.setUserProperties(userProperties);
```
### Clearing User Properties ###
@@ -231,7 +159,7 @@ amplitude.getInstance().setUserProperties(userProperties);
You may use `clearUserProperties` to clear all user properties at once. Note: the result is irreversible!
```javascript
-amplitude.getInstance().clearUserProperties();
+amplitude.clearUserProperties();
```
# Tracking Revenue #
@@ -239,7 +167,7 @@ amplitude.getInstance().clearUserProperties();
To track revenue from a user, call
```javascript
-amplitude.getInstance().logRevenue(9.99, 1, 'product');
+amplitude.logRevenue(9.99, 1, 'product');
```
The function takes a unit price, a quantity, and a product identifier. Quantity and product identifier are optional parameters.
@@ -251,14 +179,14 @@ This allows us to automatically display data relevant to revenue on the Amplitud
You can turn off logging for a given user:
```javascript
-amplitude.getInstance().setOptOut(true);
+amplitude.setOptOut(true);
```
No events will be saved or sent to the server while opt out is enabled. The opt out
setting will persist across page loads. Calling
```javascript
-amplitude.getInstance().setOptOut(false);
+amplitude.setOptOut(false);
```
will reenable logging.
@@ -268,7 +196,7 @@ will reenable logging.
You can configure Amplitude by passing an object as the third argument to the `init`:
```javascript
-amplitude.getInstance().init('YOUR_API_KEY_HERE', null, {
+amplitude.init('YOUR_API_KEY_HERE', null, {
// optional configuration options
saveEvents: true,
includeUtm: true,
@@ -298,14 +226,14 @@ This SDK automatically grabs useful data about the browser, including browser ty
By default, no version name is set. You can specify a version name to distinguish between different versions of your site by calling `setVersionName`:
```javascript
-amplitude.getInstance().setVersionName('VERSION_NAME_HERE');
+amplitude.setVersionName('VERSION_NAME_HERE');
```
### Custom Device Ids ###
Device IDs are generated randomly, although you can define a custom device ID setting it as a configuration option or by calling:
```javascript
-amplitude.getInstance().setDeviceId('CUSTOM_DEVICE_ID');
+amplitude.setDeviceId('CUSTOM_DEVICE_ID');
```
**Note: this is not recommended unless you really know what you are doing** (like if you have your own system for tracking user devices). Make sure the deviceId you set is sufficiently unique (we recommend something like a UUID - see `src/uuid.js` for an example of how to generate) to prevent conflicts with other devices in our system.
@@ -314,7 +242,7 @@ amplitude.getInstance().setDeviceId('CUSTOM_DEVICE_ID');
You can pass a callback function to logEvent, which will get called after receiving a response from the server:
```javascript
-amplitude.getInstance().logEvent("EVENT_IDENTIFIER_HERE", null, callback_function);
+amplitude.logEvent("EVENT_IDENTIFIER_HERE", null, callback_function);
```
The status and response from the server are passed to the callback function, which you might find useful. An example of a callback function which redirects the browser to another site after a response:
@@ -338,7 +266,7 @@ And then you would define a function that is called when the link is clicked lik
```javascript
var trackClickLinkA = function() {
- amplitude.getInstance().logEvent('Clicked Link A', null, function() {
+ amplitude.logEvent('Clicked Link A', null, function() {
window.location='LINK_A_URL';
});
};
@@ -347,11 +275,11 @@ var trackClickLinkA = function() {
In the case that `optOut` is true, then no event will be logged, but the callback will be called. In the case that `batchEvents` is true, if the batch requirements `eventUploadThreshold` and `eventUploadPeriodMillis` are not met when `logEvent` is called, then no request is sent, but the callback is still called. In these cases, the callback will be called with an input status of 0 and response 'No request sent'.
### Init Callbacks ###
-You can also pass a callback function to init, which will get called after the SDK finishes its asynchronous loading. *Note: the Amplitude instance is passed to the callback function as an argument*:
+You can also pass a callback function to init, which will get called after the SDK finishes its asynchronous loading. *Note: no values are passed to the init callback function*:
```javascript
-amplitude.getInstance().init('YOUR_API_KEY_HERE', 'USER_ID_HERE', null, function(instance) {
- console.log(instance.options.deviceId); // access the instance's deviceId after initialization
+amplitude.init('YOUR_API_KEY_HERE', 'USER_ID_HERE', null, function() {
+ console.log(amplitude.options.deviceId); // access Amplitude's deviceId after initialization
});
```
diff --git a/amplitude-segment-snippet.min.js b/amplitude-segment-snippet.min.js
index 6b95ad5d..bc41cf19 100644
--- a/amplitude-segment-snippet.min.js
+++ b/amplitude-segment-snippet.min.js
@@ -1,8 +1,6 @@
-(function(e,t){var n=e.amplitude||{_q:[],_iq:{}};var r=function(){this._q=[];return this;
+(function(e,t){var n=e.amplitude||{_q:[]};var r=function(){this._q=[];return this;
};function i(e){r.prototype[e]=function(){this._q.push([e].concat(Array.prototype.slice.call(arguments,0)));
-return this}}var s=["add","append","clearAll","set","setOnce","unset"];for(var o=0;o this.options.savedMaxCount) {
queue.splice(0, queue.length - this.options.savedMaxCount);
}
};
-AmplitudeClient.prototype.logEvent = function(eventType, eventProperties, callback) {
+Amplitude.prototype.logEvent = function(eventType, eventProperties, callback) {
if (!this._apiKeySet('logEvent()')) {
return -1;
}
@@ -914,7 +761,7 @@ var _isNumber = function(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
};
-AmplitudeClient.prototype.logRevenue = function(price, quantity, product) {
+Amplitude.prototype.logRevenue = function(price, quantity, product) {
// Test that the parameters are of the right type.
if (!this._apiKeySet('logRevenue()') || !_isNumber(price) || quantity !== undefined && !_isNumber(quantity)) {
// utils.log('Price and quantity arguments to logRevenue must be numbers');
@@ -933,7 +780,7 @@ AmplitudeClient.prototype.logRevenue = function(price, quantity, product) {
* Remove events in storage with event ids up to and including maxEventId. Does
* a true filter in case events get out of order or old events are removed.
*/
-AmplitudeClient.prototype.removeEvents = function (maxEventId, maxIdentifyId) {
+Amplitude.prototype.removeEvents = function (maxEventId, maxIdentifyId) {
if (maxEventId >= 0) {
var filteredEvents = [];
for (var i = 0; i < this._unsentEvents.length; i++) {
@@ -955,7 +802,7 @@ AmplitudeClient.prototype.removeEvents = function (maxEventId, maxIdentifyId) {
}
};
-AmplitudeClient.prototype.sendEvents = function(callback) {
+Amplitude.prototype.sendEvents = function(callback) {
if (!this._apiKeySet('sendEvents()')) {
return;
}
@@ -1024,7 +871,7 @@ AmplitudeClient.prototype.sendEvents = function(callback) {
}
};
-AmplitudeClient.prototype._mergeEventsAndIdentifys = function(numEvents) {
+Amplitude.prototype._mergeEventsAndIdentifys = function(numEvents) {
// coalesce events from both queues
var eventsToSend = [];
var eventIndex = 0;
@@ -1069,10 +916,17 @@ AmplitudeClient.prototype._mergeEventsAndIdentifys = function(numEvents) {
};
};
-module.exports = AmplitudeClient;
+/**
+ * @deprecated
+ */
+Amplitude.prototype.setGlobalUserProperties = Amplitude.prototype.setUserProperties;
+
+Amplitude.prototype.__VERSION__ = version;
-}, {"./cookiestorage":10,"./utm":11,"./identify":4,"json":12,"./localstorage":13,"JavaScript-MD5":14,"object":5,"./xhr":15,"ua-parser-js":16,"./utils":7,"./uuid":17,"./version":8,"./type":6,"./options":9}],
-10: [function(require, module, exports) {
+module.exports = Amplitude;
+
+}, {"./cookiestorage":3,"./utm":4,"./identify":5,"json":6,"./localstorage":7,"JavaScript-MD5":8,"object":9,"./xhr":10,"./type":11,"ua-parser-js":12,"./utils":13,"./uuid":14,"./version":15,"./options":16}],
+3: [function(require, module, exports) {
/* jshint -W020, unused: false, noempty: false, boss: true */
/*
@@ -1165,8 +1019,8 @@ cookieStorage.prototype.getStorage = function() {
module.exports = cookieStorage;
-}, {"./cookie":18,"json":12,"./localstorage":13}],
-18: [function(require, module, exports) {
+}, {"./cookie":17,"json":6,"./localstorage":7}],
+17: [function(require, module, exports) {
/*
* Cookie data
*/
@@ -1295,8 +1149,8 @@ module.exports = {
};
-}, {"./base64":19,"json":12,"top-domain":20}],
-19: [function(require, module, exports) {
+}, {"./base64":18,"json":6,"top-domain":19}],
+18: [function(require, module, exports) {
/* jshint bitwise: false */
/* global escape, unescape */
@@ -1395,8 +1249,8 @@ var Base64 = {
module.exports = Base64;
-}, {"./utf8":21}],
-21: [function(require, module, exports) {
+}, {"./utf8":20}],
+20: [function(require, module, exports) {
/* jshint bitwise: false */
/*
@@ -1456,7 +1310,7 @@ var UTF8 = {
module.exports = UTF8;
}, {}],
-12: [function(require, module, exports) {
+6: [function(require, module, exports) {
var json = window.JSON || {};
var stringify = json.stringify;
@@ -1466,8 +1320,8 @@ module.exports = parse && stringify
? JSON
: require('json-fallback');
-}, {"json-fallback":22}],
-22: [function(require, module, exports) {
+}, {"json-fallback":21}],
+21: [function(require, module, exports) {
/*
json2.js
2014-02-04
@@ -1957,7 +1811,7 @@ module.exports = parse && stringify
}());
}, {}],
-20: [function(require, module, exports) {
+19: [function(require, module, exports) {
/**
* Module dependencies.
@@ -2005,8 +1859,8 @@ function domain(url){
return match ? match[0] : '';
};
-}, {"url":23}],
-23: [function(require, module, exports) {
+}, {"url":22}],
+22: [function(require, module, exports) {
/**
* Parse the given `url`.
@@ -2091,7 +1945,7 @@ function port (protocol){
}
}, {}],
-13: [function(require, module, exports) {
+7: [function(require, module, exports) {
/* jshint -W020, unused: false, noempty: false, boss: true */
/*
@@ -2195,7 +2049,7 @@ if (!localStorage) {
module.exports = localStorage;
}, {}],
-11: [function(require, module, exports) {
+4: [function(require, module, exports) {
var getUtmParam = function(name, query) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^]*)");
@@ -2224,7 +2078,7 @@ var getUtmData = function(rawCookie, query) {
module.exports = getUtmData;
}, {}],
-4: [function(require, module, exports) {
+5: [function(require, module, exports) {
var type = require('./type');
var utils = require('./utils');
@@ -2311,8 +2165,8 @@ Identify.prototype._addOperation = function(operation, property, value) {
module.exports = Identify;
-}, {"./type":6,"./utils":7}],
-6: [function(require, module, exports) {
+}, {"./type":11,"./utils":13}],
+11: [function(require, module, exports) {
/* Taken from: https://github.com/component/type */
/**
@@ -2360,7 +2214,7 @@ module.exports = function(val){
};
}, {}],
-7: [function(require, module, exports) {
+13: [function(require, module, exports) {
var type = require('./type');
var log = function(s) {
@@ -2446,8 +2300,8 @@ module.exports = {
validateProperties: validateProperties
};
-}, {"./type":6}],
-14: [function(require, module, exports) {
+}, {"./type":11}],
+8: [function(require, module, exports) {
/*
* JavaScript MD5 1.0.1
* https://github.com/blueimp/JavaScript-MD5
@@ -2735,7 +2589,7 @@ module.exports = {
}(this));
}, {}],
-5: [function(require, module, exports) {
+9: [function(require, module, exports) {
/**
* HOP ref.
@@ -2821,7 +2675,7 @@ exports.isEmpty = function(obj){
return 0 == exports.length(obj);
};
}, {}],
-15: [function(require, module, exports) {
+10: [function(require, module, exports) {
var querystring = require('querystring');
/*
@@ -2867,8 +2721,8 @@ Request.prototype.send = function(callback) {
module.exports = Request;
-}, {"querystring":24}],
-24: [function(require, module, exports) {
+}, {"querystring":23}],
+23: [function(require, module, exports) {
/**
* Module dependencies.
@@ -2943,8 +2797,8 @@ exports.stringify = function(obj){
return pairs.join('&');
};
-}, {"trim":25,"type":26}],
-25: [function(require, module, exports) {
+}, {"trim":24,"type":25}],
+24: [function(require, module, exports) {
exports = module.exports = trim;
@@ -2964,7 +2818,7 @@ exports.right = function(str){
};
}, {}],
-26: [function(require, module, exports) {
+25: [function(require, module, exports) {
/**
* toString ref.
*/
@@ -3013,7 +2867,7 @@ function isBuffer(obj) {
}
}, {}],
-16: [function(require, module, exports) {
+12: [function(require, module, exports) {
/* jshint eqeqeq: false, forin: false */
/* global define */
@@ -3896,7 +3750,7 @@ function isBuffer(obj) {
})(this);
}, {}],
-17: [function(require, module, exports) {
+14: [function(require, module, exports) {
/* jshint bitwise: false, laxbreak: true */
/**
@@ -3930,11 +3784,11 @@ var uuid = function(a) {
module.exports = uuid;
}, {}],
-8: [function(require, module, exports) {
+15: [function(require, module, exports) {
module.exports = '2.9.0';
}, {}],
-9: [function(require, module, exports) {
+16: [function(require, module, exports) {
var language = require('./language');
// default options
@@ -3956,11 +3810,10 @@ module.exports = {
batchEvents: false,
eventUploadThreshold: 30,
eventUploadPeriodMillis: 30 * 1000, // 30s
- newBlankInstance: false
};
-}, {"./language":27}],
-27: [function(require, module, exports) {
+}, {"./language":26}],
+26: [function(require, module, exports) {
var getLanguage = function() {
return (navigator && ((navigator.languages && navigator.languages[0]) ||
navigator.language || navigator.userLanguage)) || undefined;
diff --git a/amplitude.min.js b/amplitude.min.js
index 24b5d6d4..e755e0eb 100644
--- a/amplitude.min.js
+++ b/amplitude.min.js
@@ -1,2 +1,2 @@
-(function umd(require){if("object"==typeof exports){module.exports=require("1")}else if("function"==typeof define&&define.amd){define(function(){return require("1")})}else{this["amplitude"]=require("1")}})(function outer(modules,cache,entries){var global=function(){return this}();function require(name,jumped){if(cache[name])return cache[name].exports;if(modules[name])return call(name,require);throw new Error('cannot find module "'+name+'"')}function call(id,require){var m=cache[id]={exports:{}};var mod=modules[id];var name=mod[2];var fn=mod[0];fn.call(m.exports,function(req){var dep=modules[id][1][req];return require(dep?dep:req)},m,m.exports,outer,modules,cache,entries);if(name)cache[name]=cache[id];return cache[id].exports}for(var id in entries){if(entries[id]){global[entries[id]]=require(id)}else{require(id)}}require.duo=true;require.cache=cache;require.modules=modules;return require}({1:[function(require,module,exports){var Amplitude=require("./amplitude");var old=window.amplitude||{};var newInstance=new Amplitude;newInstance._q=old._q||[];for(var instance in old._iq){if(old._iq.hasOwnProperty(instance)){newInstance.getInstance(instance)._q=old._iq[instance]._q||[]}}module.exports=newInstance},{"./amplitude":2}],2:[function(require,module,exports){var AmplitudeClient=require("./amplitude-client");var Identify=require("./identify");var object=require("object");var type=require("./type");var utils=require("./utils");var version=require("./version");var DEFAULT_OPTIONS=require("./options");var DEFAULT_INSTANCE="$default_instance";var Amplitude=function(){this.options=object.merge({},DEFAULT_OPTIONS);this._instances={}};Amplitude.prototype.getInstance=function(instance){instance=(utils.isEmptyString(instance)?DEFAULT_INSTANCE:instance).toLowerCase();var client=this._instances[instance];if(client===undefined){client=new AmplitudeClient(instance);this._instances[instance]=client}return client};Amplitude.prototype.Identify=Identify;Amplitude.prototype.runQueuedFunctions=function(){for(var i=0;ithis.options.sessionTimeout){this._newSession=true;this._sessionId=now}this._lastEventTime=now;_saveCookieData(this);if(this.options.saveEvents){this._unsentEvents=this._loadSavedUnsentEvents(this.options.unsentKey)||this._unsentEvents;this._unsentIdentifys=this._loadSavedUnsentEvents(this.options.unsentIdentifyKey)||this._unsentIdentifys;for(var i=0;i=this.options.eventUploadThreshold){this.sendEvents(callback);return true}if(!this._updateScheduled){this._updateScheduled=true;setTimeout(function(){this._updateScheduled=false;this.sendEvents()}.bind(this),this.options.eventUploadPeriodMillis)}return false};AmplitudeClient.prototype._getFromStorage=function(storage,key){return storage.getItem(key+this._storageSuffix)};AmplitudeClient.prototype._setInStorage=function(storage,key,value){storage.setItem(key+this._storageSuffix,value)};var _upgradeCookeData=function(scope){var cookieData=scope.cookieStorage.get(scope.options.cookieName);if(cookieData&&cookieData.deviceId&&cookieData.sessionId&&cookieData.lastEventTime){return}var _getAndRemoveFromLocalStorage=function(key){var value=localStorage.getItem(key);localStorage.removeItem(key);return value};var apiKeySuffix="_"+scope.options.apiKey.slice(0,6);var localStorageDeviceId=_getAndRemoveFromLocalStorage(LocalStorageKeys.DEVICE_ID+apiKeySuffix);var localStorageUserId=_getAndRemoveFromLocalStorage(LocalStorageKeys.USER_ID+apiKeySuffix);var localStorageOptOut=_getAndRemoveFromLocalStorage(LocalStorageKeys.OPT_OUT+apiKeySuffix);if(localStorageOptOut!==null&&localStorageOptOut!==undefined){localStorageOptOut=String(localStorageOptOut)==="true"}var localStorageSessionId=parseInt(_getAndRemoveFromLocalStorage(LocalStorageKeys.SESSION_ID));var localStorageLastEventTime=parseInt(_getAndRemoveFromLocalStorage(LocalStorageKeys.LAST_EVENT_TIME));var localStorageEventId=parseInt(_getAndRemoveFromLocalStorage(LocalStorageKeys.LAST_EVENT_ID));var localStorageIdentifyId=parseInt(_getAndRemoveFromLocalStorage(LocalStorageKeys.LAST_IDENTIFY_ID));var localStorageSequenceNumber=parseInt(_getAndRemoveFromLocalStorage(LocalStorageKeys.LAST_SEQUENCE_NUMBER));var _getFromCookie=function(key){return cookieData&&cookieData[key]};scope.options.deviceId=_getFromCookie("deviceId")||localStorageDeviceId;scope.options.userId=_getFromCookie("userId")||localStorageUserId;scope._sessionId=_getFromCookie("sessionId")||localStorageSessionId||scope._sessionId;scope._lastEventTime=_getFromCookie("lastEventTime")||localStorageLastEventTime||scope._lastEventTime;scope._eventId=_getFromCookie("eventId")||localStorageEventId||scope._eventId;scope._identifyId=_getFromCookie("identifyId")||localStorageIdentifyId||scope._identifyId;scope._sequenceNumber=_getFromCookie("sequenceNumber")||localStorageSequenceNumber||scope._sequenceNumber;scope.options.optOut=localStorageOptOut||false;if(cookieData&&cookieData.optOut!==undefined&&cookieData.optOut!==null){scope.options.optOut=String(cookieData.optOut)==="true"}_saveCookieData(scope)};var _loadCookieData=function(scope){var cookieData=scope.cookieStorage.get(scope.options.cookieName+scope._storageSuffix);if(cookieData){if(cookieData.deviceId){scope.options.deviceId=cookieData.deviceId}if(cookieData.userId){scope.options.userId=cookieData.userId}if(cookieData.optOut!==null&&cookieData.optOut!==undefined){scope.options.optOut=cookieData.optOut}if(cookieData.sessionId){scope._sessionId=parseInt(cookieData.sessionId)}if(cookieData.lastEventTime){scope._lastEventTime=parseInt(cookieData.lastEventTime)}if(cookieData.eventId){scope._eventId=parseInt(cookieData.eventId)}if(cookieData.identifyId){scope._identifyId=parseInt(cookieData.identifyId)}if(cookieData.sequenceNumber){scope._sequenceNumber=parseInt(cookieData.sequenceNumber)}}};var _saveCookieData=function(scope){scope.cookieStorage.set(scope.options.cookieName+scope._storageSuffix,{deviceId:scope.options.deviceId,userId:scope.options.userId,optOut:scope.options.optOut,sessionId:scope._sessionId,lastEventTime:scope._lastEventTime,eventId:scope._eventId,identifyId:scope._identifyId,sequenceNumber:scope._sequenceNumber})};AmplitudeClient.prototype._initUtmData=function(queryParams,cookieParams){queryParams=queryParams||location.search;cookieParams=cookieParams||this.cookieStorage.get("__utmz");this._utmProperties=getUtmData(cookieParams,queryParams)};AmplitudeClient.prototype._getReferrer=function(){return document.referrer};AmplitudeClient.prototype._getReferringDomain=function(referrer){if(referrer===null||referrer===undefined||referrer===""){return null}var parts=referrer.split("/");if(parts.length>=3){return parts[2]}return null};AmplitudeClient.prototype._saveReferrer=function(referrer){if(referrer===null||referrer===undefined||referrer===""){return}var referring_domain=this._getReferringDomain(referrer);var identify=(new Identify).setOnce("initial_referrer",referrer);identify.setOnce("initial_referring_domain",referring_domain);var hasSessionStorage=false;try{if(window.sessionStorage){hasSessionStorage=true}}catch(e){}if(hasSessionStorage&&!this._getFromStorage(sessionStorage,LocalStorageKeys.REFERRER)||!hasSessionStorage){identify.set("referrer",referrer).set("referring_domain",referring_domain);if(hasSessionStorage){this._setInStorage(sessionStorage,LocalStorageKeys.REFERRER,referrer)}}this.identify(identify)};AmplitudeClient.prototype.saveEvents=function(){if(!this._apiKeySet("saveEvents()")){return}try{this._setInStorage(localStorage,this.options.unsentKey,JSON.stringify(this._unsentEvents));this._setInStorage(localStorage,this.options.unsentIdentifyKey,JSON.stringify(this._unsentIdentifys))}catch(e){}};AmplitudeClient.prototype.setDomain=function(domain){if(!this._apiKeySet("setDomain()")){return}try{this.cookieStorage.options({domain:domain});this.options.domain=this.cookieStorage.options().domain;_loadCookieData(this);_saveCookieData(this)}catch(e){utils.log(e)}};AmplitudeClient.prototype.setUserId=function(userId){if(!this._apiKeySet("setUserId()")){return}try{this.options.userId=userId!==undefined&&userId!==null&&""+userId||null;_saveCookieData(this)}catch(e){utils.log(e)}};AmplitudeClient.prototype.setOptOut=function(enable){if(!this._apiKeySet("setOptOut()")){return}try{this.options.optOut=enable;_saveCookieData(this)}catch(e){utils.log(e)}};AmplitudeClient.prototype.setDeviceId=function(deviceId){if(!this._apiKeySet("setDeviceId()")){return}try{if(deviceId){this.options.deviceId=""+deviceId;_saveCookieData(this)}}catch(e){utils.log(e)}};AmplitudeClient.prototype.setUserProperties=function(userProperties){if(!this._apiKeySet("setUserProperties()")){return}var identify=new Identify;for(var property in userProperties){if(userProperties.hasOwnProperty(property)){identify.set(property,userProperties[property])}}this.identify(identify)};AmplitudeClient.prototype.clearUserProperties=function(){if(!this._apiKeySet("clearUserProperties()")){return}var identify=new Identify;identify.clearAll();this.identify(identify)};AmplitudeClient.prototype.identify=function(identify){if(!this._apiKeySet("identify()")){return}if(type(identify)==="object"&&"_q"in identify){var instance=new Identify;for(var i=0;i0){this._logEvent(IDENTIFY_EVENT,null,null,identify.userPropertiesOperations)}};AmplitudeClient.prototype.setVersionName=function(versionName){try{this.options.versionName=versionName}catch(e){utils.log(e)}};AmplitudeClient.prototype._truncate=function(value){if(type(value)==="array"){for(var i=0;iMAX_STRING_LENGTH?value.substring(0,MAX_STRING_LENGTH):value}return value};AmplitudeClient.prototype._logEvent=function(eventType,eventProperties,apiProperties,userProperties,callback){if(type(callback)!=="function"){callback=null}if(!eventType||this.options.optOut){if(callback){callback(0,"No request sent")}return}try{var eventId;if(eventType===IDENTIFY_EVENT){eventId=this.nextIdentifyId()}else{eventId=this.nextEventId()}var sequenceNumber=this.nextSequenceNumber();var eventTime=(new Date).getTime();var ua=this._ua;if(!this._sessionId||!this._lastEventTime||eventTime-this._lastEventTime>this.options.sessionTimeout){this._sessionId=eventTime}this._lastEventTime=eventTime;_saveCookieData(this);userProperties=userProperties||{};if(eventType!==IDENTIFY_EVENT){object.merge(userProperties,this._utmProperties)}apiProperties=apiProperties||{};eventProperties=eventProperties||{};var event={device_id:this.options.deviceId,user_id:this.options.userId||this.options.deviceId,timestamp:eventTime,event_id:eventId,session_id:this._sessionId||-1,event_type:eventType,version_name:this.options.versionName||null,platform:this.options.platform,os_name:ua.browser.name||null,os_version:ua.browser.major||null,device_model:ua.os.name||null,language:this.options.language,api_properties:apiProperties,event_properties:this._truncate(utils.validateProperties(eventProperties)),user_properties:this._truncate(userProperties),uuid:UUID(),library:{name:"amplitude-js",version:version},sequence_number:sequenceNumber};if(eventType===IDENTIFY_EVENT){this._unsentIdentifys.push(event);this._limitEventsQueued(this._unsentIdentifys)}else{this._unsentEvents.push(event);this._limitEventsQueued(this._unsentEvents)}if(this.options.saveEvents){this.saveEvents()}if(!this._sendEventsIfReady(callback)&&callback){callback(0,"No request sent")}return eventId}catch(e){utils.log(e)}};AmplitudeClient.prototype._limitEventsQueued=function(queue){if(queue.length>this.options.savedMaxCount){queue.splice(0,queue.length-this.options.savedMaxCount)}};AmplitudeClient.prototype.logEvent=function(eventType,eventProperties,callback){if(!this._apiKeySet("logEvent()")){return-1}return this._logEvent(eventType,eventProperties,null,null,callback)};var _isNumber=function(n){return!isNaN(parseFloat(n))&&isFinite(n)};AmplitudeClient.prototype.logRevenue=function(price,quantity,product){if(!this._apiKeySet("logRevenue()")||!_isNumber(price)||quantity!==undefined&&!_isNumber(quantity)){return-1}return this._logEvent("revenue_amount",{},{productId:product,special:"revenue_amount",quantity:quantity||1,price:price})};AmplitudeClient.prototype.removeEvents=function(maxEventId,maxIdentifyId){if(maxEventId>=0){var filteredEvents=[];for(var i=0;imaxEventId){filteredEvents.push(this._unsentEvents[i])}}this._unsentEvents=filteredEvents}if(maxIdentifyId>=0){var filteredIdentifys=[];for(var j=0;jmaxIdentifyId){filteredIdentifys.push(this._unsentIdentifys[j])}}this._unsentIdentifys=filteredIdentifys}};AmplitudeClient.prototype.sendEvents=function(callback){if(!this._apiKeySet("sendEvents()")){return}if(!this._sending&&!this.options.optOut&&this._unsentCount()>0){this._sending=true;var url=("https:"===window.location.protocol?"https":"http")+"://"+this.options.apiEndpoint+"/";var numEvents=Math.min(this._unsentCount(),this.options.uploadBatchSize);var mergedEvents=this._mergeEventsAndIdentifys(numEvents);var maxEventId=mergedEvents.maxEventId;var maxIdentifyId=mergedEvents.maxIdentifyId;var events=JSON.stringify(mergedEvents.eventsToSend);var uploadTime=(new Date).getTime();var data={client:this.options.apiKey,e:events,v:API_VERSION,upload_time:uploadTime,checksum:md5(API_VERSION+this.options.apiKey+events+uploadTime)};var scope=this;new Request(url,data).send(function(status,response){scope._sending=false;try{if(status===200&&response==="success"){scope.removeEvents(maxEventId,maxIdentifyId);if(scope.options.saveEvents){scope.saveEvents()}if(!scope._sendEventsIfReady(callback)&&callback){callback(status,response)}}else if(status===413){if(scope.options.uploadBatchSize===1){scope.removeEvents(maxEventId,maxIdentifyId)}scope.options.uploadBatchSize=Math.ceil(numEvents/2);scope.sendEvents(callback)}else if(callback){callback(status,response)}}catch(e){}})}else if(callback){callback(0,"No request sent")}};AmplitudeClient.prototype._mergeEventsAndIdentifys=function(numEvents){var eventsToSend=[];var eventIndex=0;var maxEventId=-1;var identifyIndex=0;var maxIdentifyId=-1;while(eventsToSend.length=this._unsentIdentifys.length){event=this._unsentEvents[eventIndex++];maxEventId=event.event_id}else if(eventIndex>=this._unsentEvents.length){event=this._unsentIdentifys[identifyIndex++];maxIdentifyId=event.event_id}else{if(!("sequence_number"in this._unsentEvents[eventIndex])||this._unsentEvents[eventIndex].sequence_number>2;enc2=(chr1&3)<<4|chr2>>4;enc3=(chr2&15)<<2|chr3>>6;enc4=chr3&63;if(isNaN(chr2)){enc3=enc4=64}else if(isNaN(chr3)){enc4=64}output=output+Base64._keyStr.charAt(enc1)+Base64._keyStr.charAt(enc2)+Base64._keyStr.charAt(enc3)+Base64._keyStr.charAt(enc4)}return output},decode:function(input){try{if(window.btoa&&window.atob){return decodeURIComponent(escape(window.atob(input)))}}catch(e){}return Base64._decode(input)},_decode:function(input){var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(i>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}output=UTF8.decode(output);return output}};module.exports=Base64},{"./utf8":21}],21:[function(require,module,exports){var UTF8={encode:function(s){var utftext="";for(var n=0;n127&&c<2048){utftext+=String.fromCharCode(c>>6|192);utftext+=String.fromCharCode(c&63|128)}else{utftext+=String.fromCharCode(c>>12|224);utftext+=String.fromCharCode(c>>6&63|128);utftext+=String.fromCharCode(c&63|128)}}return utftext},decode:function(utftext){var s="";var i=0;var c=0,c1=0,c2=0;while(i191&&c<224){c1=utftext.charCodeAt(i+1);s+=String.fromCharCode((c&31)<<6|c1&63);i+=2}else{c1=utftext.charCodeAt(i+1);c2=utftext.charCodeAt(i+2);s+=String.fromCharCode((c&15)<<12|(c1&63)<<6|c2&63);i+=3}}return s}};module.exports=UTF8},{}],12:[function(require,module,exports){var json=window.JSON||{};var stringify=json.stringify;var parse=json.parse;module.exports=parse&&stringify?JSON:require("json-fallback")},{"json-fallback":22}],22:[function(require,module,exports){(function(){"use strict";var JSON=module.exports={};function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()}}var cx,escapable,gap,indent,meta,rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i0){if(!this.userPropertiesOperations.hasOwnProperty(AMP_OP_CLEAR_ALL)){utils.log("Need to send $clearAll on its own Identify object without any other operations, skipping $clearAll")}return this}this.userPropertiesOperations[AMP_OP_CLEAR_ALL]="-";return this};Identify.prototype.set=function(property,value){this._addOperation(AMP_OP_SET,property,value);return this};Identify.prototype.setOnce=function(property,value){this._addOperation(AMP_OP_SET_ONCE,property,value);return this};Identify.prototype.unset=function(property){this._addOperation(AMP_OP_UNSET,property,"-");return this};Identify.prototype._addOperation=function(operation,property,value){if(this.userPropertiesOperations.hasOwnProperty(AMP_OP_CLEAR_ALL)){utils.log("This identify already contains a $clearAll operation, skipping operation "+operation);return}if(this.properties.indexOf(property)!==-1){utils.log('User property "'+property+'" already used in this identify, skipping operation '+operation);return}if(!this.userPropertiesOperations.hasOwnProperty(operation)){this.userPropertiesOperations[operation]={}}this.userPropertiesOperations[operation][property]=value;this.properties.push(property)};module.exports=Identify},{"./type":6,"./utils":7}],6:[function(require,module,exports){var toString=Object.prototype.toString;module.exports=function(val){switch(toString.call(val)){case"[object Date]":return"date";case"[object RegExp]":return"regexp";case"[object Arguments]":return"arguments";case"[object Array]":return"array";case"[object Error]":return"error"}if(val===null){return"null"}if(val===undefined){return"undefined"}if(val!==val){return"nan"}if(val&&val.nodeType===1){return"element"}if(typeof Buffer!=="undefined"&&Buffer.isBuffer(val)){return"buffer"}val=val.valueOf?val.valueOf():Object.prototype.valueOf.apply(val);return typeof val}},{}],7:[function(require,module,exports){var type=require("./type");var log=function(s){try{console.log("[Amplitude] "+s)}catch(e){}};var isEmptyString=function(str){return!str||str.length===0};var validateProperties=function(properties){var propsType=type(properties);if(propsType!=="object"){log("Error: invalid event properties format. Expecting Javascript object, received "+propsType+", ignoring");return{}}var copy={};for(var property in properties){if(!properties.hasOwnProperty(property)){continue}var key=property;var keyType=type(key);if(keyType!=="string"){log("WARNING: Non-string property key, received type "+keyType+', coercing to string "'+key+'"');key=String(key)}var value=validatePropertyValue(key,properties[property]);if(value===null){continue}copy[key]=value}return copy};var invalidValueTypes=["null","nan","undefined","function","arguments","regexp","element"];var validatePropertyValue=function(key,value){var valueType=type(value);if(invalidValueTypes.indexOf(valueType)!==-1){log('WARNING: Property key "'+key+'" with invalid value type '+valueType+", ignoring");value=null}else if(valueType==="error"){value=String(value);log('WARNING: Property key "'+key+'" with value type error, coercing to '+value)}else if(valueType==="array"){var arrayCopy=[];for(var i=0;i>16)+(y>>16)+(lsw>>16);return msw<<16|lsw&65535}function bit_rol(num,cnt){return num<>>32-cnt}function md5_cmn(q,a,b,x,s,t){return safe_add(bit_rol(safe_add(safe_add(a,q),safe_add(x,t)),s),b)}function md5_ff(a,b,c,d,x,s,t){return md5_cmn(b&c|~b&d,a,b,x,s,t)}function md5_gg(a,b,c,d,x,s,t){return md5_cmn(b&d|c&~d,a,b,x,s,t)}function md5_hh(a,b,c,d,x,s,t){return md5_cmn(b^c^d,a,b,x,s,t)}function md5_ii(a,b,c,d,x,s,t){return md5_cmn(c^(b|~d),a,b,x,s,t)}function binl_md5(x,len){x[len>>5]|=128<>>9<<4)+14]=len;var i,olda,oldb,oldc,oldd,a=1732584193,b=-271733879,c=-1732584194,d=271733878;for(i=0;i>5]>>>i%32&255)}return output}function rstr2binl(input){var i,output=[];output[(input.length>>2)-1]=undefined;for(i=0;i>5]|=(input.charCodeAt(i/8)&255)<16){bkey=binl_md5(bkey,key.length*8)}for(i=0;i<16;i+=1){ipad[i]=bkey[i]^909522486;opad[i]=bkey[i]^1549556828}hash=binl_md5(ipad.concat(rstr2binl(data)),512+data.length*8);return binl2rstr(binl_md5(opad.concat(hash),512+128))}function rstr2hex(input){var hex_tab="0123456789abcdef",output="",x,i;for(i=0;i>>4&15)+hex_tab.charAt(x&15)}return output}function str2rstr_utf8(input){return unescape(encodeURIComponent(input))}function raw_md5(s){return rstr_md5(str2rstr_utf8(s))}function hex_md5(s){return rstr2hex(raw_md5(s))}function raw_hmac_md5(k,d){return rstr_hmac_md5(str2rstr_utf8(k),str2rstr_utf8(d))}function hex_hmac_md5(k,d){return rstr2hex(raw_hmac_md5(k,d))}function md5(string,key,raw){if(!key){if(!raw){return hex_md5(string)}return raw_md5(string)}if(!raw){return hex_hmac_md5(key,string)}return raw_hmac_md5(key,string)}if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports){exports=module.exports=md5}exports.md5=md5}else{if(typeof define==="function"&&define.amd){define(function(){return md5})}else{$.md5=md5}}})(this)},{}],5:[function(require,module,exports){var has=Object.prototype.hasOwnProperty;exports.keys=Object.keys||function(obj){var keys=[];for(var key in obj){if(has.call(obj,key)){keys.push(key)}}return keys};exports.values=function(obj){var vals=[];for(var key in obj){if(has.call(obj,key)){vals.push(obj[key])}}return vals};exports.merge=function(a,b){for(var key in b){if(has.call(b,key)){a[key]=b[key]}}return a};exports.length=function(obj){return exports.keys(obj).length};exports.isEmpty=function(obj){return 0==exports.length(obj)}},{}],15:[function(require,module,exports){var querystring=require("querystring");var Request=function(url,data){this.url=url;this.data=data||{}};Request.prototype.send=function(callback){var isIE=window.XDomainRequest?true:false;if(isIE){var xdr=new window.XDomainRequest;xdr.open("POST",this.url,true);xdr.onload=function(){callback(200,xdr.responseText)};xdr.onerror=function(){if(xdr.responseText==="Request Entity Too Large"){callback(413,xdr.responseText)}else{callback(500,xdr.responseText)}};xdr.ontimeout=function(){};xdr.onprogress=function(){};xdr.send(querystring.stringify(this.data))}else{var xhr=new XMLHttpRequest;xhr.open("POST",this.url,true);xhr.onreadystatechange=function(){if(xhr.readyState===4){callback(xhr.status,xhr.responseText)}};xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");xhr.send(querystring.stringify(this.data))}};module.exports=Request},{querystring:24}],24:[function(require,module,exports){var encode=encodeURIComponent;var decode=decodeURIComponent;var trim=require("trim");var type=require("type");exports.parse=function(str){if("string"!=typeof str)return{};str=trim(str);if(""==str)return{};if("?"==str.charAt(0))str=str.slice(1);var obj={};var pairs=str.split("&");for(var i=0;i0){if(q.length==2){if(typeof q[1]==FUNC_TYPE){result[q[0]]=q[1].call(this,match)}else{result[q[0]]=q[1]}}else if(q.length==3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){result[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{result[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length==4){result[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{result[q]=match?match:undefined}}}}i+=2}return result},str:function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;j