From cc7d3a9e4c37e3f9d7de1789a38794e861c3e40a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20F=2E=20Mu=C3=B1oz?= Date: Fri, 21 Oct 2022 10:22:59 -0500 Subject: [PATCH] Fetch support when XMLHttpRequest isn't available This is mainly useful for service workers, which creates compatibility for MV3 chrome extensions --- dist/mixpanel.amd.js | 130 ++++++++++++---- dist/mixpanel.cjs.js | 130 ++++++++++++---- dist/mixpanel.globals.js | 130 ++++++++++++---- dist/mixpanel.min.js | 199 +++++++++++++------------ dist/mixpanel.umd.js | 130 ++++++++++++---- examples/commonjs-browserify/bundle.js | 130 ++++++++++++---- examples/es2015-babelify/bundle.js | 74 ++++++++- examples/umd-webpack/bundle.js | 130 ++++++++++++---- src/mixpanel-core.js | 74 ++++++++- src/mixpanel-people.js | 2 +- 10 files changed, 828 insertions(+), 301 deletions(-) diff --git a/dist/mixpanel.amd.js b/dist/mixpanel.amd.js index c3236be5..92f84aee 100644 --- a/dist/mixpanel.amd.js +++ b/dist/mixpanel.amd.js @@ -37,7 +37,7 @@ define(function () { 'use strict'; var hasOwnProperty = ObjProto.hasOwnProperty; var windowConsole = window$1.console; var navigator = window$1.navigator; - var document$1 = window$1.document; + var document = window$1.document; var windowOpera = window$1.opera; var screen = window$1.screen; var userAgent = navigator.userAgent; @@ -978,7 +978,7 @@ define(function () { 'use strict'; _.cookie = { get: function(name) { var nameEQ = name + '='; - var ca = document$1.cookie.split(';'); + var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { @@ -1009,7 +1009,7 @@ define(function () { 'use strict'; if (domain_override) { cdomain = '; domain=' + domain_override; } else if (is_cross_subdomain) { - var domain = extract_domain(document$1.location.hostname); + var domain = extract_domain(document.location.hostname); cdomain = domain ? '; domain=.' + domain : ''; } @@ -1027,7 +1027,7 @@ define(function () { 'use strict'; secure += '; secure'; } - document$1.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; + document.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; }, set: function(name, value, days, is_cross_subdomain, is_secure, is_cross_site, domain_override) { @@ -1036,7 +1036,7 @@ define(function () { 'use strict'; if (domain_override) { cdomain = '; domain=' + domain_override; } else if (is_cross_subdomain) { - var domain = extract_domain(document$1.location.hostname); + var domain = extract_domain(document.location.hostname); cdomain = domain ? '; domain=.' + domain : ''; } @@ -1055,7 +1055,7 @@ define(function () { 'use strict'; } var new_cookie_val = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; - document$1.cookie = new_cookie_val; + document.cookie = new_cookie_val; return new_cookie_val; }, @@ -1257,13 +1257,13 @@ define(function () { 'use strict'; function getElementsBySelector(selector) { // Attempt to fail gracefully in lesser browsers - if (!document$1.getElementsByTagName) { + if (!document.getElementsByTagName) { return []; } // Split selector in to tokens var tokens = selector.split(' '); var token, bits, tagName, found, foundCount, i, j, k, elements, currentContextIndex; - var currentContext = [document$1]; + var currentContext = [document]; for (i = 0; i < tokens.length; i++) { token = tokens[i].replace(/^\s+/, '').replace(/\s+$/, ''); if (token.indexOf('#') > -1) { @@ -1271,7 +1271,7 @@ define(function () { 'use strict'; bits = token.split('#'); tagName = bits[0]; var id = bits[1]; - var element = document$1.getElementById(id); + var element = document.getElementById(id); if (!element || (tagName && element.nodeName.toLowerCase() != tagName)) { // element not found or tag with that ID not found, return false return []; @@ -1418,7 +1418,7 @@ define(function () { 'use strict'; kw = '', params = {}; _.each(campaign_keywords, function(kwkey) { - kw = _.getQueryParam(document$1.URL, kwkey); + kw = _.getQueryParam(document.URL, kwkey); if (kw.length) { params[kwkey] = kw; } @@ -1599,8 +1599,8 @@ define(function () { 'use strict'; return _.extend(_.strip_empty_properties({ '$os': _.info.os(), '$browser': _.info.browser(userAgent, navigator.vendor, windowOpera), - '$referrer': document$1.referrer, - '$referring_domain': _.info.referringDomain(document$1.referrer), + '$referrer': document.referrer, + '$referring_domain': _.info.referringDomain(document.referrer), '$device': _.info.device(userAgent) }), { '$current_url': window$1.location.href, @@ -1626,7 +1626,7 @@ define(function () { 'use strict'; pageviewInfo: function(page) { return _.strip_empty_properties({ 'mp_page': page, - 'mp_referrer': document$1.referrer, + 'mp_referrer': document.referrer, 'mp_browser': _.info.browser(userAgent, navigator.vendor, windowOpera), 'mp_platform': _.info.os() }); @@ -4055,11 +4055,12 @@ define(function () { 'use strict'; // http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ // https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#withCredentials var USE_XHR = (window$1.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()); + var USE_FETCH = !_.isUndefined(fetch) && typeof(fetch) === 'function' // IE<10 does not support cross-origin XHR's but script tags // with defer won't block window.onload; ENQUEUE_REQUESTS // should only be true for Opera<12 - var ENQUEUE_REQUESTS = !USE_XHR && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); + var ENQUEUE_REQUESTS = !USE_XHR && !USE_FETCH && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); // save reference to navigator.sendBeacon so it can be minified var sendBeacon = null; @@ -4276,7 +4277,7 @@ define(function () { 'use strict'; } }); window$1.addEventListener('visibilitychange', function() { - if (document$1['visibilityState'] === 'hidden') { + if (document['visibilityState'] === 'hidden') { flush_on_unload(); } }); @@ -4309,12 +4310,12 @@ define(function () { 'use strict'; // update persistence with info on referrer, UTM params, etc MixpanelLib.prototype._set_default_superprops = function() { - this['persistence'].update_search_keyword(document$1.referrer); + this['persistence'].update_search_keyword(document.referrer); if (this.get_config('store_google')) { this['persistence'].update_campaign_params(); } if (this.get_config('save_referrer')) { - this['persistence'].update_referrer_info(document$1.referrer); + this['persistence'].update_referrer_info(document.referrer); } }; @@ -4362,7 +4363,7 @@ define(function () { 'use strict'; return null; } - if (USE_XHR) { + if (USE_XHR || USE_FETCH) { var callback_function = function(response) { callback(response, data); }; @@ -4402,7 +4403,7 @@ define(function () { 'use strict'; options = null; } options = _.extend(DEFAULT_OPTIONS, options || {}); - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { options.method = 'GET'; } var use_post = options.method === 'POST'; @@ -4415,7 +4416,7 @@ define(function () { 'use strict'; if (this.get_config('test')) { data['test'] = 1; } if (verbose_mode) { data['verbose'] = 1; } if (this.get_config('img')) { data['img'] = 1; } - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { if (callback) { data['callback'] = callback; } else if (verbose_mode || this.get_config('test')) { @@ -4439,9 +4440,9 @@ define(function () { 'use strict'; var lib = this; if ('img' in data) { - var img = document$1.createElement('img'); + var img = document.createElement('img'); img.src = url; - document$1.body.appendChild(img); + document.body.appendChild(img); } else if (use_sendBeacon) { try { succeeded = sendBeacon(url, body_data); @@ -4525,13 +4526,78 @@ define(function () { 'use strict'; lib.report_error(e); succeeded = false; } + } else if (USE_FETCH) { + try { + var headers = this.get_config('xhr_headers'); + if (use_post) { + headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + + var fetchOpts = { + method: options.method, + mode: 'cors', + credentials: 'include', + headers: headers, + body: body_data + }; + + fetch(url, fetchOpts) + .then(function (response) { + return response.text().then(function (body) { + return { + status: response.status, + statusText: response.statusText, + headers: response.headers, + body: body + }; + }); + }) + .then(function (res) { + if (res.status === 200) { + if (callback) { + var body = res.body; + if (verbose_mode) { + var response; + try { + response = _.JSONDecode(body); + } catch (e) { + lib.report_error(e); + if (options.ignore_json_errors) { + response = body; + } else { + return; + } + } + callback(response); + } else { + callback(Number(body)); + } + } + } else { + var error = 'Bad HTTP status: ' + res.status + ' ' + res.statusText; + lib.report_error(error); + + if (callback) { + if (verbose_mode) { + var xhr_req = { status: res.status, responseHeaders: res.headers }; + callback({ status: 0, error: error, xhr_req: xhr_req }); + } else { + callback(0); + } + } + } + }); + } catch (e) { + lib.report_error(e); + succeeded = false; + } } else { - var script = document$1.createElement('script'); + var script = document.createElement('script'); script.type = 'text/javascript'; script.async = true; script.defer = true; script.src = url; - var s = document$1.getElementsByTagName('script')[0]; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(script, s); } @@ -4968,7 +5034,7 @@ define(function () { 'use strict'; */ MixpanelLib.prototype.track_pageview = function(page) { if (_.isUndefined(page)) { - page = document$1.location.href; + page = document.location.href; } this.track('mp_page_view', _.info.pageviewInfo(page)); }; @@ -5925,7 +5991,7 @@ define(function () { 'use strict'; function do_scroll_check() { try { - document$1.documentElement.doScroll('left'); + document.documentElement.doScroll('left'); } catch(e) { setTimeout(do_scroll_check, 1); return; @@ -5934,19 +6000,19 @@ define(function () { 'use strict'; dom_loaded_handler(); } - if (document$1.addEventListener) { - if (document$1.readyState === 'complete') { + if (document.addEventListener) { + if (document.readyState === 'complete') { // safari 4 can fire the DOMContentLoaded event before loading all // external JS (including this file). you will see some copypasta // on the internet that checks for 'complete' and 'loaded', but // 'loaded' is an IE thing dom_loaded_handler(); } else { - document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false); + document.addEventListener('DOMContentLoaded', dom_loaded_handler, false); } - } else if (document$1.attachEvent) { + } else if (document.attachEvent) { // IE - document$1.attachEvent('onreadystatechange', dom_loaded_handler); + document.attachEvent('onreadystatechange', dom_loaded_handler); // check to make sure we arn't in a frame var toplevel = false; @@ -5956,7 +6022,7 @@ define(function () { 'use strict'; // noop } - if (document$1.documentElement.doScroll && toplevel) { + if (document.documentElement.doScroll && toplevel) { do_scroll_check(); } } diff --git a/dist/mixpanel.cjs.js b/dist/mixpanel.cjs.js index b60df003..a125c3e8 100644 --- a/dist/mixpanel.cjs.js +++ b/dist/mixpanel.cjs.js @@ -37,7 +37,7 @@ var toString = ObjProto.toString; var hasOwnProperty = ObjProto.hasOwnProperty; var windowConsole = window$1.console; var navigator = window$1.navigator; -var document$1 = window$1.document; +var document = window$1.document; var windowOpera = window$1.opera; var screen = window$1.screen; var userAgent = navigator.userAgent; @@ -978,7 +978,7 @@ _.getQueryParam = function(url, param) { _.cookie = { get: function(name) { var nameEQ = name + '='; - var ca = document$1.cookie.split(';'); + var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { @@ -1009,7 +1009,7 @@ _.cookie = { if (domain_override) { cdomain = '; domain=' + domain_override; } else if (is_cross_subdomain) { - var domain = extract_domain(document$1.location.hostname); + var domain = extract_domain(document.location.hostname); cdomain = domain ? '; domain=.' + domain : ''; } @@ -1027,7 +1027,7 @@ _.cookie = { secure += '; secure'; } - document$1.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; + document.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; }, set: function(name, value, days, is_cross_subdomain, is_secure, is_cross_site, domain_override) { @@ -1036,7 +1036,7 @@ _.cookie = { if (domain_override) { cdomain = '; domain=' + domain_override; } else if (is_cross_subdomain) { - var domain = extract_domain(document$1.location.hostname); + var domain = extract_domain(document.location.hostname); cdomain = domain ? '; domain=.' + domain : ''; } @@ -1055,7 +1055,7 @@ _.cookie = { } var new_cookie_val = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; - document$1.cookie = new_cookie_val; + document.cookie = new_cookie_val; return new_cookie_val; }, @@ -1257,13 +1257,13 @@ _.dom_query = (function() { function getElementsBySelector(selector) { // Attempt to fail gracefully in lesser browsers - if (!document$1.getElementsByTagName) { + if (!document.getElementsByTagName) { return []; } // Split selector in to tokens var tokens = selector.split(' '); var token, bits, tagName, found, foundCount, i, j, k, elements, currentContextIndex; - var currentContext = [document$1]; + var currentContext = [document]; for (i = 0; i < tokens.length; i++) { token = tokens[i].replace(/^\s+/, '').replace(/\s+$/, ''); if (token.indexOf('#') > -1) { @@ -1271,7 +1271,7 @@ _.dom_query = (function() { bits = token.split('#'); tagName = bits[0]; var id = bits[1]; - var element = document$1.getElementById(id); + var element = document.getElementById(id); if (!element || (tagName && element.nodeName.toLowerCase() != tagName)) { // element not found or tag with that ID not found, return false return []; @@ -1418,7 +1418,7 @@ _.info = { kw = '', params = {}; _.each(campaign_keywords, function(kwkey) { - kw = _.getQueryParam(document$1.URL, kwkey); + kw = _.getQueryParam(document.URL, kwkey); if (kw.length) { params[kwkey] = kw; } @@ -1599,8 +1599,8 @@ _.info = { return _.extend(_.strip_empty_properties({ '$os': _.info.os(), '$browser': _.info.browser(userAgent, navigator.vendor, windowOpera), - '$referrer': document$1.referrer, - '$referring_domain': _.info.referringDomain(document$1.referrer), + '$referrer': document.referrer, + '$referring_domain': _.info.referringDomain(document.referrer), '$device': _.info.device(userAgent) }), { '$current_url': window$1.location.href, @@ -1626,7 +1626,7 @@ _.info = { pageviewInfo: function(page) { return _.strip_empty_properties({ 'mp_page': page, - 'mp_referrer': document$1.referrer, + 'mp_referrer': document.referrer, 'mp_browser': _.info.browser(userAgent, navigator.vendor, windowOpera), 'mp_platform': _.info.os() }); @@ -4055,11 +4055,12 @@ var NOOP_FUNC = function() {}; // http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ // https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#withCredentials var USE_XHR = (window$1.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()); +var USE_FETCH = !_.isUndefined(fetch) && typeof(fetch) === 'function' // IE<10 does not support cross-origin XHR's but script tags // with defer won't block window.onload; ENQUEUE_REQUESTS // should only be true for Opera<12 -var ENQUEUE_REQUESTS = !USE_XHR && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); +var ENQUEUE_REQUESTS = !USE_XHR && !USE_FETCH && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); // save reference to navigator.sendBeacon so it can be minified var sendBeacon = null; @@ -4276,7 +4277,7 @@ MixpanelLib.prototype._init = function(token, config, name) { } }); window$1.addEventListener('visibilitychange', function() { - if (document$1['visibilityState'] === 'hidden') { + if (document['visibilityState'] === 'hidden') { flush_on_unload(); } }); @@ -4309,12 +4310,12 @@ MixpanelLib.prototype._loaded = function() { // update persistence with info on referrer, UTM params, etc MixpanelLib.prototype._set_default_superprops = function() { - this['persistence'].update_search_keyword(document$1.referrer); + this['persistence'].update_search_keyword(document.referrer); if (this.get_config('store_google')) { this['persistence'].update_campaign_params(); } if (this.get_config('save_referrer')) { - this['persistence'].update_referrer_info(document$1.referrer); + this['persistence'].update_referrer_info(document.referrer); } }; @@ -4362,7 +4363,7 @@ MixpanelLib.prototype._prepare_callback = function(callback, data) { return null; } - if (USE_XHR) { + if (USE_XHR || USE_FETCH) { var callback_function = function(response) { callback(response, data); }; @@ -4402,7 +4403,7 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) { options = null; } options = _.extend(DEFAULT_OPTIONS, options || {}); - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { options.method = 'GET'; } var use_post = options.method === 'POST'; @@ -4415,7 +4416,7 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) { if (this.get_config('test')) { data['test'] = 1; } if (verbose_mode) { data['verbose'] = 1; } if (this.get_config('img')) { data['img'] = 1; } - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { if (callback) { data['callback'] = callback; } else if (verbose_mode || this.get_config('test')) { @@ -4439,9 +4440,9 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) { var lib = this; if ('img' in data) { - var img = document$1.createElement('img'); + var img = document.createElement('img'); img.src = url; - document$1.body.appendChild(img); + document.body.appendChild(img); } else if (use_sendBeacon) { try { succeeded = sendBeacon(url, body_data); @@ -4525,13 +4526,78 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) { lib.report_error(e); succeeded = false; } + } else if (USE_FETCH) { + try { + var headers = this.get_config('xhr_headers'); + if (use_post) { + headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + + var fetchOpts = { + method: options.method, + mode: 'cors', + credentials: 'include', + headers: headers, + body: body_data + }; + + fetch(url, fetchOpts) + .then(function (response) { + return response.text().then(function (body) { + return { + status: response.status, + statusText: response.statusText, + headers: response.headers, + body: body + }; + }); + }) + .then(function (res) { + if (res.status === 200) { + if (callback) { + var body = res.body; + if (verbose_mode) { + var response; + try { + response = _.JSONDecode(body); + } catch (e) { + lib.report_error(e); + if (options.ignore_json_errors) { + response = body; + } else { + return; + } + } + callback(response); + } else { + callback(Number(body)); + } + } + } else { + var error = 'Bad HTTP status: ' + res.status + ' ' + res.statusText; + lib.report_error(error); + + if (callback) { + if (verbose_mode) { + var xhr_req = { status: res.status, responseHeaders: res.headers }; + callback({ status: 0, error: error, xhr_req: xhr_req }); + } else { + callback(0); + } + } + } + }); + } catch (e) { + lib.report_error(e); + succeeded = false; + } } else { - var script = document$1.createElement('script'); + var script = document.createElement('script'); script.type = 'text/javascript'; script.async = true; script.defer = true; script.src = url; - var s = document$1.getElementsByTagName('script')[0]; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(script, s); } @@ -4968,7 +5034,7 @@ MixpanelLib.prototype.get_group = function (group_key, group_id) { */ MixpanelLib.prototype.track_pageview = function(page) { if (_.isUndefined(page)) { - page = document$1.location.href; + page = document.location.href; } this.track('mp_page_view', _.info.pageviewInfo(page)); }; @@ -5925,7 +5991,7 @@ var add_dom_loaded_handler = function() { function do_scroll_check() { try { - document$1.documentElement.doScroll('left'); + document.documentElement.doScroll('left'); } catch(e) { setTimeout(do_scroll_check, 1); return; @@ -5934,19 +6000,19 @@ var add_dom_loaded_handler = function() { dom_loaded_handler(); } - if (document$1.addEventListener) { - if (document$1.readyState === 'complete') { + if (document.addEventListener) { + if (document.readyState === 'complete') { // safari 4 can fire the DOMContentLoaded event before loading all // external JS (including this file). you will see some copypasta // on the internet that checks for 'complete' and 'loaded', but // 'loaded' is an IE thing dom_loaded_handler(); } else { - document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false); + document.addEventListener('DOMContentLoaded', dom_loaded_handler, false); } - } else if (document$1.attachEvent) { + } else if (document.attachEvent) { // IE - document$1.attachEvent('onreadystatechange', dom_loaded_handler); + document.attachEvent('onreadystatechange', dom_loaded_handler); // check to make sure we arn't in a frame var toplevel = false; @@ -5956,7 +6022,7 @@ var add_dom_loaded_handler = function() { // noop } - if (document$1.documentElement.doScroll && toplevel) { + if (document.documentElement.doScroll && toplevel) { do_scroll_check(); } } diff --git a/dist/mixpanel.globals.js b/dist/mixpanel.globals.js index 867bfe48..5c3a5141 100644 --- a/dist/mixpanel.globals.js +++ b/dist/mixpanel.globals.js @@ -38,7 +38,7 @@ var hasOwnProperty = ObjProto.hasOwnProperty; var windowConsole = window$1.console; var navigator = window$1.navigator; - var document$1 = window$1.document; + var document = window$1.document; var windowOpera = window$1.opera; var screen = window$1.screen; var userAgent = navigator.userAgent; @@ -979,7 +979,7 @@ _.cookie = { get: function(name) { var nameEQ = name + '='; - var ca = document$1.cookie.split(';'); + var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { @@ -1010,7 +1010,7 @@ if (domain_override) { cdomain = '; domain=' + domain_override; } else if (is_cross_subdomain) { - var domain = extract_domain(document$1.location.hostname); + var domain = extract_domain(document.location.hostname); cdomain = domain ? '; domain=.' + domain : ''; } @@ -1028,7 +1028,7 @@ secure += '; secure'; } - document$1.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; + document.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; }, set: function(name, value, days, is_cross_subdomain, is_secure, is_cross_site, domain_override) { @@ -1037,7 +1037,7 @@ if (domain_override) { cdomain = '; domain=' + domain_override; } else if (is_cross_subdomain) { - var domain = extract_domain(document$1.location.hostname); + var domain = extract_domain(document.location.hostname); cdomain = domain ? '; domain=.' + domain : ''; } @@ -1056,7 +1056,7 @@ } var new_cookie_val = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; - document$1.cookie = new_cookie_val; + document.cookie = new_cookie_val; return new_cookie_val; }, @@ -1258,13 +1258,13 @@ function getElementsBySelector(selector) { // Attempt to fail gracefully in lesser browsers - if (!document$1.getElementsByTagName) { + if (!document.getElementsByTagName) { return []; } // Split selector in to tokens var tokens = selector.split(' '); var token, bits, tagName, found, foundCount, i, j, k, elements, currentContextIndex; - var currentContext = [document$1]; + var currentContext = [document]; for (i = 0; i < tokens.length; i++) { token = tokens[i].replace(/^\s+/, '').replace(/\s+$/, ''); if (token.indexOf('#') > -1) { @@ -1272,7 +1272,7 @@ bits = token.split('#'); tagName = bits[0]; var id = bits[1]; - var element = document$1.getElementById(id); + var element = document.getElementById(id); if (!element || (tagName && element.nodeName.toLowerCase() != tagName)) { // element not found or tag with that ID not found, return false return []; @@ -1419,7 +1419,7 @@ kw = '', params = {}; _.each(campaign_keywords, function(kwkey) { - kw = _.getQueryParam(document$1.URL, kwkey); + kw = _.getQueryParam(document.URL, kwkey); if (kw.length) { params[kwkey] = kw; } @@ -1600,8 +1600,8 @@ return _.extend(_.strip_empty_properties({ '$os': _.info.os(), '$browser': _.info.browser(userAgent, navigator.vendor, windowOpera), - '$referrer': document$1.referrer, - '$referring_domain': _.info.referringDomain(document$1.referrer), + '$referrer': document.referrer, + '$referring_domain': _.info.referringDomain(document.referrer), '$device': _.info.device(userAgent) }), { '$current_url': window$1.location.href, @@ -1627,7 +1627,7 @@ pageviewInfo: function(page) { return _.strip_empty_properties({ 'mp_page': page, - 'mp_referrer': document$1.referrer, + 'mp_referrer': document.referrer, 'mp_browser': _.info.browser(userAgent, navigator.vendor, windowOpera), 'mp_platform': _.info.os() }); @@ -4056,11 +4056,12 @@ // http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ // https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#withCredentials var USE_XHR = (window$1.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()); + var USE_FETCH = !_.isUndefined(fetch) && typeof(fetch) === 'function' // IE<10 does not support cross-origin XHR's but script tags // with defer won't block window.onload; ENQUEUE_REQUESTS // should only be true for Opera<12 - var ENQUEUE_REQUESTS = !USE_XHR && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); + var ENQUEUE_REQUESTS = !USE_XHR && !USE_FETCH && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); // save reference to navigator.sendBeacon so it can be minified var sendBeacon = null; @@ -4277,7 +4278,7 @@ } }); window$1.addEventListener('visibilitychange', function() { - if (document$1['visibilityState'] === 'hidden') { + if (document['visibilityState'] === 'hidden') { flush_on_unload(); } }); @@ -4310,12 +4311,12 @@ // update persistence with info on referrer, UTM params, etc MixpanelLib.prototype._set_default_superprops = function() { - this['persistence'].update_search_keyword(document$1.referrer); + this['persistence'].update_search_keyword(document.referrer); if (this.get_config('store_google')) { this['persistence'].update_campaign_params(); } if (this.get_config('save_referrer')) { - this['persistence'].update_referrer_info(document$1.referrer); + this['persistence'].update_referrer_info(document.referrer); } }; @@ -4363,7 +4364,7 @@ return null; } - if (USE_XHR) { + if (USE_XHR || USE_FETCH) { var callback_function = function(response) { callback(response, data); }; @@ -4403,7 +4404,7 @@ options = null; } options = _.extend(DEFAULT_OPTIONS, options || {}); - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { options.method = 'GET'; } var use_post = options.method === 'POST'; @@ -4416,7 +4417,7 @@ if (this.get_config('test')) { data['test'] = 1; } if (verbose_mode) { data['verbose'] = 1; } if (this.get_config('img')) { data['img'] = 1; } - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { if (callback) { data['callback'] = callback; } else if (verbose_mode || this.get_config('test')) { @@ -4440,9 +4441,9 @@ var lib = this; if ('img' in data) { - var img = document$1.createElement('img'); + var img = document.createElement('img'); img.src = url; - document$1.body.appendChild(img); + document.body.appendChild(img); } else if (use_sendBeacon) { try { succeeded = sendBeacon(url, body_data); @@ -4526,13 +4527,78 @@ lib.report_error(e); succeeded = false; } + } else if (USE_FETCH) { + try { + var headers = this.get_config('xhr_headers'); + if (use_post) { + headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + + var fetchOpts = { + method: options.method, + mode: 'cors', + credentials: 'include', + headers: headers, + body: body_data + }; + + fetch(url, fetchOpts) + .then(function (response) { + return response.text().then(function (body) { + return { + status: response.status, + statusText: response.statusText, + headers: response.headers, + body: body + }; + }); + }) + .then(function (res) { + if (res.status === 200) { + if (callback) { + var body = res.body; + if (verbose_mode) { + var response; + try { + response = _.JSONDecode(body); + } catch (e) { + lib.report_error(e); + if (options.ignore_json_errors) { + response = body; + } else { + return; + } + } + callback(response); + } else { + callback(Number(body)); + } + } + } else { + var error = 'Bad HTTP status: ' + res.status + ' ' + res.statusText; + lib.report_error(error); + + if (callback) { + if (verbose_mode) { + var xhr_req = { status: res.status, responseHeaders: res.headers }; + callback({ status: 0, error: error, xhr_req: xhr_req }); + } else { + callback(0); + } + } + } + }); + } catch (e) { + lib.report_error(e); + succeeded = false; + } } else { - var script = document$1.createElement('script'); + var script = document.createElement('script'); script.type = 'text/javascript'; script.async = true; script.defer = true; script.src = url; - var s = document$1.getElementsByTagName('script')[0]; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(script, s); } @@ -4969,7 +5035,7 @@ */ MixpanelLib.prototype.track_pageview = function(page) { if (_.isUndefined(page)) { - page = document$1.location.href; + page = document.location.href; } this.track('mp_page_view', _.info.pageviewInfo(page)); }; @@ -5926,7 +5992,7 @@ function do_scroll_check() { try { - document$1.documentElement.doScroll('left'); + document.documentElement.doScroll('left'); } catch(e) { setTimeout(do_scroll_check, 1); return; @@ -5935,19 +6001,19 @@ dom_loaded_handler(); } - if (document$1.addEventListener) { - if (document$1.readyState === 'complete') { + if (document.addEventListener) { + if (document.readyState === 'complete') { // safari 4 can fire the DOMContentLoaded event before loading all // external JS (including this file). you will see some copypasta // on the internet that checks for 'complete' and 'loaded', but // 'loaded' is an IE thing dom_loaded_handler(); } else { - document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false); + document.addEventListener('DOMContentLoaded', dom_loaded_handler, false); } - } else if (document$1.attachEvent) { + } else if (document.attachEvent) { // IE - document$1.attachEvent('onreadystatechange', dom_loaded_handler); + document.attachEvent('onreadystatechange', dom_loaded_handler); // check to make sure we arn't in a frame var toplevel = false; @@ -5957,7 +6023,7 @@ // noop } - if (document$1.documentElement.doScroll && toplevel) { + if (document.documentElement.doScroll && toplevel) { do_scroll_check(); } } diff --git a/dist/mixpanel.min.js b/dist/mixpanel.min.js index 74a81998..43442577 100644 --- a/dist/mixpanel.min.js +++ b/dist/mixpanel.min.js @@ -1,103 +1,104 @@ (function() { -var k=void 0,l=!0,q=null,F=!1; -(function(){function Aa(){function a(){if(!a.qc)la=a.qc=l,ma=F,c.a(G,function(a){a.dc()})}function b(){try{t.documentElement.doScroll("left")}catch(d){setTimeout(b,1);return}a()}if(t.addEventListener)"complete"===t.readyState?a():t.addEventListener("DOMContentLoaded",a,F);else if(t.attachEvent){t.attachEvent("onreadystatechange",a);var d=F;try{d=A.frameElement===q}catch(n){}t.documentElement.doScroll&&d&&b()}c.Gb(A,"load",a,l)}function Ba(){w.init=function(a,b,d){if(d)return w[d]||(w[d]=G[d]=T(a, -b,d),w[d].da()),w[d];d=w;if(G.mixpanel)d=G.mixpanel;else if(a)d=T(a,b,"mixpanel"),d.da(),G.mixpanel=d;w=d;1===ca&&(A.mixpanel=w);Ca()}}function Ca(){c.a(G,function(a,b){"mixpanel"!==b&&(w[b]=a)});w._=c}function da(a){a=c.e(a)?a:c.g(a)?{}:{days:a};return c.extend({},Da,a)}function T(a,b,d){var n,f="mixpanel"===d?w:w[d];if(f&&0===ca)n=f;else{if(f&&!c.isArray(f)){p.error("You have already initialized "+d);return}n=new e}n.Ya={};n.R(a,b,d);n.people=new i;n.people.R(n);J=J||n.c("debug");!c.g(f)&&c.isArray(f)&& -(n.ua.call(n.people,f.people),n.ua(f));return n}function e(){}function O(){}function Ea(a){return a}function m(a){this.props={};this.gb=F;this.name=a.persistence_name?"mp_"+a.persistence_name:"mp_"+a.token+"_mixpanel";var b=a.persistence;if("cookie"!==b&&"localStorage"!==b)p.F("Unknown persistence type "+b+"; falling back to cookie"),b=a.persistence="cookie";this.h="localStorage"===b&&c.localStorage.la()?c.localStorage:c.cookie;this.load();this.Zb(a);this.kd(a);this.save()}function i(){}function s(){} -function C(a,b){this.G=b.G;this.W=new H(a,{G:c.bind(this.j,this),h:b.h});this.A=b.A;this.Nc=b.Oc;this.ea=b.ea;this.Xc=b.Yc;this.S=this.A.batch_size;this.ia=this.A.batch_flush_interval_ms;this.oa=!this.A.batch_autostart;this.Ea=0}function na(a,b){var d=[];c.a(a,function(a){var c=a.id;if(c in b){if(c=b[c],c!==q)a.payload=c,d.push(a)}else d.push(a)});return d}function oa(a,b){var d=[];c.a(a,function(a){a.id&&!b[a.id]&&d.push(a)});return d}function H(a,b){b=b||{};this.I=a;this.h=b.h||window.localStorage; -this.j=b.G||c.bind(pa.error,pa);this.Oa=new qa(a,{h:this.h});this.ma=b.ma||q;this.D=[]}function qa(a,b){b=b||{};this.I=a;this.h=b.h||window.localStorage;this.Eb=b.Eb||100;this.Tb=b.Tb||2E3}function U(){this.Bb="submit"}function L(){this.Bb="click"}function D(){}function ra(a){var b=Fa,d=a.split("."),d=d[d.length-1];if(4a?"0"+a:a}return a.getUTCFullYear()+"-"+b(a.getUTCMonth()+1)+"-"+b(a.getUTCDate())+ -"T"+b(a.getUTCHours())+":"+b(a.getUTCMinutes())+":"+b(a.getUTCSeconds())};c.pa=function(a){var b={};c.a(a,function(a,n){c.Na(a)&&0=h;)f()}function d(){var a,b,d="",c;if('"'===h)for(;f();){if('"'===h)return f(),d;if("\\"===h)if(f(),"u"===h){for(b=c=0;4>b;b+=1){a=parseInt(f(),16);if(!isFinite(a))break;c=16*c+a}d+=String.fromCharCode(c)}else if("string"===typeof j[h])d+=j[h];else break;else d+=h}g("Bad string")}function c(){var a;a="";"-"===h&&(a="-",f("-"));for(;"0"<=h&&"9">=h;)a+=h,f();if("."===h)for(a+= -".";f()&&"0"<=h&&"9">=h;)a+=h;if("e"===h||"E"===h){a+=h;f();if("-"===h||"+"===h)a+=h,f();for(;"0"<=h&&"9">=h;)a+=h,f()}a=+a;if(isFinite(a))return a;g("Bad number")}function f(a){a&&a!==h&&g("Expected '"+a+"' instead of '"+h+"'");h=o.charAt(e);e+=1;return h}function g(a){a=new SyntaxError(a);a.nd=e;a.text=o;throw a;}var e,h,j={'"':'"',"\\":"\\","/":"/",b:"\u0008",f:"\u000c",n:"\n",r:"\r",t:"\t"},o,r;r=function(){b();switch(h){case "{":var e;a:{var y,j={};if("{"===h){f("{");b();if("}"===h){f("}");e= -j;break a}for(;h;){y=d();b();f(":");Object.hasOwnProperty.call(j,y)&&g('Duplicate key "'+y+'"');j[y]=r();b();if("}"===h){f("}");e=j;break a}f(",");b()}}g("Bad object")}return e;case "[":a:{e=[];if("["===h){f("[");b();if("]"===h){f("]");y=e;break a}for(;h;){e.push(r());b();if("]"===h){f("]");y=e;break a}f(",");b()}}g("Bad array")}return y;case '"':return d();case "-":return c();default:return"0"<=h&&"9">=h?c():a()}};return function(a){o=a;e=0;h=" ";a=r();b();h&&g("Syntax error");return a}}();c.kc= -function(a){var b,d,n,f,g=0,e=0,h="",h=[];if(!a)return a;a=c.ld(a);do b=a.charCodeAt(g++),d=a.charCodeAt(g++),n=a.charCodeAt(g++),f=b<<16|d<<8|n,b=f>>18&63,d=f>>12&63,n=f>>6&63,f&=63,h[e++]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(b)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(d)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(n)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(f); -while(ge?c++:h=127e?String.fromCharCode(e>>6|192,e&63|128):String.fromCharCode(e>>12|224,e>>6&63|128,e&63|128);h!==q&&(c>d&&(b+=a.substring(d,c)),b+=h,d=c=g+1)}c>d&&(b+=a.substring(d,a.length));return b};c.Xa=function(){function a(){function a(b, -d){var c,f=0;for(c=0;ca?"0"+a:a}return a.getUTCFullYear()+"-"+b(a.getUTCMonth()+1)+"-"+b(a.getUTCDate())+ +"T"+b(a.getUTCHours())+":"+b(a.getUTCMinutes())+":"+b(a.getUTCSeconds())};c.pa=function(a){var b={};c.a(a,function(a,j){c.Na(a)&&0=h;)f()}function d(){var a,b,d="",c;if('"'===h)for(;f();){if('"'===h)return f(),d;if("\\"===h)if(f(),"u"===h){for(b=c=0;4>b;b+=1){a=parseInt(f(),16);if(!isFinite(a))break;c=16*c+a}d+=String.fromCharCode(c)}else if("string"===typeof e[h])d+=e[h];else break;else d+=h}g("Bad string")}function c(){var a;a="";"-"===h&&(a="-",f("-"));for(;"0"<=h&&"9">=h;)a+=h,f();if("."===h)for(a+= +".";f()&&"0"<=h&&"9">=h;)a+=h;if("e"===h||"E"===h){a+=h;f();if("-"===h||"+"===h)a+=h,f();for(;"0"<=h&&"9">=h;)a+=h,f()}a=+a;if(isFinite(a))return a;g("Bad number")}function f(a){a&&a!==h&&g("Expected '"+a+"' instead of '"+h+"'");h=o.charAt(w);w+=1;return h}function g(a){a=new SyntaxError(a);a.od=w;a.text=o;throw a;}var w,h,e={'"':'"',"\\":"\\","/":"/",b:"\u0008",f:"\u000c",n:"\n",r:"\r",t:"\t"},o,r;r=function(){b();switch(h){case "{":var e;a:{var w,k={};if("{"===h){f("{");b();if("}"===h){f("}");e= +k;break a}for(;h;){w=d();b();f(":");Object.hasOwnProperty.call(k,w)&&g('Duplicate key "'+w+'"');k[w]=r();b();if("}"===h){f("}");e=k;break a}f(",");b()}}g("Bad object")}return e;case "[":a:{e=[];if("["===h){f("[");b();if("]"===h){f("]");w=e;break a}for(;h;){e.push(r());b();if("]"===h){f("]");w=e;break a}f(",");b()}}g("Bad array")}return w;case '"':return d();case "-":return c();default:return"0"<=h&&"9">=h?c():a()}};return function(a){o=a;w=0;h=" ";a=r();b();h&&g("Syntax error");return a}}();c.mc= +function(a){var b,d,j,f,g=0,e=0,h="",h=[];if(!a)return a;a=c.md(a);do b=a.charCodeAt(g++),d=a.charCodeAt(g++),j=a.charCodeAt(g++),f=b<<16|d<<8|j,b=f>>18&63,d=f>>12&63,j=f>>6&63,f&=63,h[e++]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(b)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(d)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(j)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(f); +while(ge?c++:h=127e?String.fromCharCode(e>>6|192,e&63|128):String.fromCharCode(e>>12|224,e>>6&63|128,e&63|128);h!==q&&(c>d&&(b+=a.substring(d,c)),b+=h,d=c=g+1)}c>d&&(b+=a.substring(d,a.length));return b};c.Xa=function(){function a(){function a(b, +d){var c,j=0;for(c=0;cu?(Oa.error("Timeout waiting for mutex on "+r+"; clearing lock. ["+j+"]"),i.removeItem(t),i.removeItem(p),f()):setTimeout(function(){try{a()}catch(c){b&& -b(c)}},v*(Math.random()+0.1))}!c&&"function"!==typeof b&&(c=b,b=q);var j=c||(new Date).getTime()+"|"+Math.random(),o=(new Date).getTime(),r=this.I,v=this.Eb,u=this.Tb,i=this.h,m=r+":X",p=r+":Y",t=r+":Z";try{if(V(i,l))f();else throw Error("localStorage support check failed");}catch(s){b&&b(s)}};var pa=ga("batch");H.prototype.Ha=function(a,b,d){var n={id:ea(),flushAfter:(new Date).getTime()+2*b,payload:a};this.Oa.Wa(c.bind(function(){var b;try{var c=this.X();c.push(n);(b=this.Sa(c))&&this.D.push(n)}catch(e){this.j("Error enqueueing item", -a),b=F}d&&d(b)},this),c.bind(function(a){this.j("Error acquiring storage lock",a);d&&d(F)},this),this.ma)};H.prototype.rc=function(a){var b=this.D.slice(0,a);if(b.lengthg.flushAfter&&!n[g.id]&&(g.Dc=l,b.push(g),b.length>=a))break}}}return b};H.prototype.Hc=function(a,b){var d={};c.a(a,function(a){d[a]=l});this.D=oa(this.D,d);var n=c.bind(function(){var b;try{var c= -this.X(),c=oa(c,d);if(b=this.Sa(c))for(var c=this.X(),n=0;ne.length)this.Y();else{this.Ib=l;var h=c.bind(function(e){this.Ib=F;try{var g=F;if(a.Xb)this.W.hd(i);else if(c.e(e)&&"timeout"===e.error&&(new Date).getTime()-d>=b)this.j("Network timeout; retrying"),this.flush(); -else if(c.e(e)&&e.L&&(500<=e.L.status||429===e.L.status||"timeout"===e.error)){var h=2*this.ia,j=e.L.responseHeaders;if(j){var o=j["Retry-After"];o&&(h=1E3*parseInt(o,10)||h)}h=Math.min(6E5,h);this.j("Error; retry in "+h+" ms");this.Kb(h)}else if(c.e(e)&&e.L&&413===e.L.status)if(1=u.timeout?"timeout":"Bad HTTP status: "+u.status+" "+u.statusText,o.l(a),e&&(j?e({status:0,error:a,L:u}):e(0))};u.send(i)}catch(x){o.l(x),f=F}else i=t.createElement("script"),i.type="text/javascript",i.async=l,i.defer=l,i.src=a,s=t.getElementsByTagName("script")[0],s.parentNode.insertBefore(i,s);return f};e.prototype.ua=function(a){function b(a,b){c.a(a,function(a){if(c.isArray(a[0])){var d=b;c.a(a,function(a){d=d[a[0]].apply(d,a.slice(1))})}else this[a[0]].apply(this, -a.slice(1))},b)}var d,e=[],f=[],g=[];c.a(a,function(a){a&&(d=a[0],c.isArray(d)?g.push(a):"function"===typeof a?a.call(this):c.isArray(a)&&"alias"===d?e.push(a):c.isArray(a)&&-1!==d.indexOf("track")&&"function"===typeof this[d]?g.push(a):f.push(a))},this);b(e,this);b(f,this);b(g,this)};e.prototype.fb=function(){return!!this.p.ha};e.prototype.yc=function(){var a=this.c("token");if(!this.fb()){var b=c.bind(function(b){return new C("__mpq_"+a+b.Ra,{A:this.config,Oc:c.bind(function(a,c,e){this.k(this.c("api_host")+ -b.C,this.Za(a),c,this.ab(e,a))},this),ea:c.bind(function(a){return this.cb("before_send_"+b.type,a)},this),G:this.c("error_reporter"),Yc:c.bind(this.Sb,this)})},this);this.p={ha:b({type:"events",C:"/track/",Ra:"_ev"}),Fc:b({type:"people",C:"/engage/",Ra:"_pp"}),wc:b({type:"groups",C:"/groups/",Ra:"_gr"})}}this.c("batch_autostart")&&this.Rb()};e.prototype.Rb=function(){if(this.fb())this.N=l,c.a(this.p,function(a){a.start()})};e.prototype.Sb=function(){this.N=F;c.a(this.p,function(a){a.stop();a.clear()})}; -e.prototype.push=function(a){this.ua([a])};e.prototype.disable=function(a){"undefined"===typeof a?this.O.oc=l:this.ra=this.ra.concat(a)};e.prototype.Za=function(a){a=c.aa(a);"base64"===this.c("api_payload_format")&&(a=c.kc(a));return{data:a}};e.prototype.Aa=function(a,b){var d=c.truncate(a.data,255),e=a.C,f=a.Ca,g=a.Wc,i=a.Pc||{},b=b||O,h=l,j=c.bind(function(){i.Qb||(d=this.cb("before_send_"+a.type,d));return d?(p.log("MIXPANEL REQUEST:"),p.log(d),this.k(e,this.Za(d),i,this.ab(b,d))):q},this);this.N&& -!g?f.Ha(d,function(a){a?b(1,d):j()}):h=j();return h&&d};e.prototype.m=P(function(a,b,d,e){!e&&"function"===typeof d&&(e=d,d=q);var d=d||{},f=d.transport;if(f)d.Ua=f;f=d.send_immediately;"function"!==typeof e&&(e=O);if(c.g(a))this.l("No event name provided to mixpanel.track");else if(this.$a(a))e(0);else{b=b||{};b.token=this.c("token");var g=this.persistence.Ic(a);c.g(g)||(b.$duration=parseFloat((((new Date).getTime()-g)/1E3).toFixed(3)));this.eb();b=c.extend({},c.info.V(),this.persistence.V(),this.K, -b);g=this.c("property_blacklist");c.isArray(g)?c.a(g,function(a){delete b[a]}):this.l("Invalid value for property_blacklist config: "+g);return this.Aa({type:"events",data:{event:a,properties:b},C:this.c("api_host")+"/track/",Ca:this.p.ha,Wc:f,Pc:d},e)}});e.prototype.Uc=P(function(a,b,d){c.isArray(b)||(b=[b]);var e={};e[a]=b;this.o(e);return this.people.set(a,b,d)});e.prototype.hc=P(function(a,b,c){var e=this.s(a);if(e===k){var f={};f[a]=[b];this.o(f)}else-1===e.indexOf(b)&&(e.push(b),this.o(f)); -return this.people.Z(a,b,c)});e.prototype.Jc=P(function(a,b,c){var e=this.s(a);if(e!==k){var f=e.indexOf(b);-1(w.__SV||0)? -p.F("Version mismatch; please ensure you're using the latest version of the Mixpanel code snippet."):(c.a(w._i,function(a){a&&c.isArray(a)&&(G[a[a.length-1]]=T.apply(this,a))}),Ba(),w.init(),c.a(G,function(a){a.da()}),Aa())})()})(); +Mozilla:/rv:(\d+(\.\d+)?)/}[c.info.T(a,b,d)];if(b===l)return q;a=a.match(b);return!a?q:parseFloat(a[a.length-2])},Qa:function(){return/Windows/i.test(z)?/Phone/.test(z)||/WPDesktop/.test(z)?"Windows Phone":"Windows":/(iPhone|iPad|iPod)/.test(z)?"iOS":/Android/.test(z)?"Android":/(BlackBerry|PlayBook|BB10)/i.test(z)?"BlackBerry":/Mac/i.test(z)?"Mac OS X":/Linux/.test(z)?"Linux":/CrOS/.test(z)?"Chrome OS":""},pb:function(a){return/Windows Phone/i.test(a)||/WPDesktop/.test(a)?"Windows Phone":/iPad/.test(a)? +"iPad":/iPod/.test(a)?"iPod Touch":/iPhone/.test(a)?"iPhone":/(BlackBerry|PlayBook|BB10)/i.test(a)?"BlackBerry":/Android/.test(a)?"Android":""},Gb:function(a){a=a.split("/");return 3<=a.length?a[2]:""},V:function(){return c.extend(c.pa({$os:c.info.Qa(),$browser:c.info.T(z,E.vendor,R),$referrer:t.referrer,$referring_domain:c.info.Gb(t.referrer),$device:c.info.pb(z)}),{$current_url:A.location.href,$browser_version:c.info.Da(z,E.vendor,R),$screen_height:$.height,$screen_width:$.width,mp_lib:"web",$lib_version:"2.45.0", +$insert_id:fa(),time:c.timestamp()/1E3})},Hc:function(){return c.extend(c.pa({$os:c.info.Qa(),$browser:c.info.T(z,E.vendor,R)}),{$browser_version:c.info.Da(z,E.vendor,R)})},Fc:function(a){return c.pa({mp_page:a,mp_referrer:t.referrer,mp_browser:c.info.T(z,E.vendor,R),mp_platform:c.info.Qa()})}};var Ha=/[a-z0-9][a-z0-9-]*\.[a-z]+$/i,Ga=/[a-z0-9][a-z0-9-]+\.[a-z.]{2,6}$/i,aa=q,ba=q;if("undefined"!==typeof JSON)aa=JSON.stringify,ba=JSON.parse;aa=aa||c.aa;ba=ba||c.G;c.toArray=c.L;c.isObject=c.g;c.JSONEncode= +c.aa;c.JSONDecode=c.G;c.isBlockedUA=c.xb;c.isEmptyObject=c.ka;c.info=c.info;c.info.device=c.info.pb;c.info.browser=c.info.T;c.info.browserVersion=c.info.Da;c.info.properties=c.info.V;D.prototype.ga=function(){};D.prototype.Ia=function(){};D.prototype.Ba=function(){};D.prototype.La=function(a){this.zb=a;return this};D.prototype.m=function(a,b,d,j){var f=this,g=c.rc(a);if(0===g.length)p.error("The DOM query ("+a+") returned 0 elements");else return c.a(g,function(a){c.Hb(a,this.Cb,function(a){var c= +{},g=f.ga(d,this),e=f.zb.c("track_links_timeout");f.Ia(a,this,c);window.setTimeout(f.Xb(j,g,c,m),e);f.zb.m(b,g,f.Xb(j,g,c))})},this),m};D.prototype.Xb=function(a,b,c,j){var j=j||F,f=this;return function(){if(!c.nc)c.nc=m,a&&a(j,b)===F||f.Ba(b,c,j)}};D.prototype.ga=function(a,b){return"function"===typeof a?a(b):c.extend({},a)};c.wb(L,D);L.prototype.ga=function(a,b){var c=L.$c.ga.apply(this,arguments);if(b.href)c.url=b.href;return c};L.prototype.Ia=function(a,b,c){c.Ab=2===a.which||a.metaKey||a.ctrlKey|| +"_blank"===b.target;c.href=b.href;c.Ab||a.preventDefault()};L.prototype.Ba=function(a,b){b.Ab||setTimeout(function(){window.location=b.href},0)};c.wb(V,D);V.prototype.Ia=function(a,b,c){c.element=b;a.preventDefault()};V.prototype.Ba=function(a,b){setTimeout(function(){b.element.submit()},0)};var Pa=ha("lock");ra.prototype.Wa=function(a,b,c){function j(){i.setItem(t,"1");try{a()}finally{i.removeItem(t),i.getItem(p)===k&&i.removeItem(p),i.getItem(n)===k&&i.removeItem(n)}}function f(){i.setItem(n,k); +e(g,function(){i.getItem(n)===k?j():h(function(){i.getItem(p)!==k?f():e(function(){return!i.getItem(t)},j)})})}function g(){var a=i.getItem(p);if(a&&a!==k)return F;i.setItem(p,k);if(i.getItem(p)===k)return m;if(!W(i,m))throw Error("localStorage support dropped while acquiring lock");return F}function e(a,b){a()?b():h(function(){e(a,b)})}function h(a){(new Date).getTime()-o>u?(Pa.error("Timeout waiting for mutex on "+r+"; clearing lock. ["+k+"]"),i.removeItem(t),i.removeItem(p),f()):setTimeout(function(){try{a()}catch(c){b&& +b(c)}},v*(Math.random()+0.1))}!c&&"function"!==typeof b&&(c=b,b=q);var k=c||(new Date).getTime()+"|"+Math.random(),o=(new Date).getTime(),r=this.K,v=this.Fb,u=this.Vb,i=this.h,n=r+":X",p=r+":Y",t=r+":Z";try{if(W(i,m))f();else throw Error("localStorage support check failed");}catch(Qa){b&&b(Qa)}};var qa=ha("batch");H.prototype.Ha=function(a,b,d){var j={id:fa(),flushAfter:(new Date).getTime()+2*b,payload:a};this.Oa.Wa(c.bind(function(){var b;try{var c=this.X();c.push(j);(b=this.Sa(c))&&this.D.push(j)}catch(e){this.j("Error enqueueing item", +a),b=F}d&&d(b)},this),c.bind(function(a){this.j("Error acquiring storage lock",a);d&&d(F)},this),this.ma)};H.prototype.tc=function(a){var b=this.D.slice(0,a);if(b.lengthg.flushAfter&&!j[g.id]&&(g.Ec=m,b.push(g),b.length>=a))break}}}return b};H.prototype.Ic=function(a,b){var d={};c.a(a,function(a){d[a]=m});this.D=pa(this.D,d);var j=c.bind(function(){var b;try{var c= +this.X(),c=pa(c,d);if(b=this.Sa(c))for(var c=this.X(),j=0;je.length)this.Y();else{this.Jb=m;var h=c.bind(function(e){this.Jb=F;try{var g=F;if(a.Zb)this.W.jd(w);else if(c.g(e)&&"timeout"===e.error&&(new Date).getTime()-d>=b)this.j("Network timeout; retrying"), +this.flush();else if(c.g(e)&&e.F&&(500<=e.F.status||429===e.F.status||"timeout"===e.error)){var h=2*this.ia,k=e.F.responseHeaders;if(k){var i=k["Retry-After"];i&&(h=1E3*parseInt(i,10)||h)}h=Math.min(6E5,h);this.j("Error; retry in "+h+" ms");this.Lb(h)}else if(c.g(e)&&e.F&&413===e.F.status)if(1=u.timeout?"timeout":"Bad HTTP status: "+u.status+" "+u.statusText,o.l(a),e&&(k?e({status:0,error:a,F:u}):e(0))};u.send(i)}catch(y){o.l(y),f=F}else if(T)try{s=this.c("xhr_headers"),g&&(s["Content-Type"]="application/x-www-form-urlencoded"),fetch(a,{method:d.method,mode:"cors",pd:"include",headers:s,body:i}).Ub(function(a){return a.text().Ub(function(b){return{status:a.status,statusText:a.statusText, +headers:a.headers,body:b}})}).Ub(function(a){if(200===a.status){if(e)if(a=a.body,k){var b;try{b=c.G(a)}catch(f){if(o.l(f),d.tb)b=a;else return}e(b)}else e(Number(a))}else b="Bad HTTP status: "+a.status+" "+a.statusText,o.l(b),e&&(k?e({status:0,error:b,F:{status:a.status,sd:a.headers}}):e(0))})}catch(z){o.l(z),f=F}else i=t.createElement("script"),i.type="text/javascript",i.async=m,i.defer=m,i.src=a,s=t.getElementsByTagName("script")[0],s.parentNode.insertBefore(i,s);return f};e.prototype.ua=function(a){function b(a, +b){c.a(a,function(a){if(c.isArray(a[0])){var d=b;c.a(a,function(a){d=d[a[0]].apply(d,a.slice(1))})}else this[a[0]].apply(this,a.slice(1))},b)}var d,e=[],f=[],g=[];c.a(a,function(a){a&&(d=a[0],c.isArray(d)?g.push(a):"function"===typeof a?a.call(this):c.isArray(a)&&"alias"===d?e.push(a):c.isArray(a)&&-1!==d.indexOf("track")&&"function"===typeof this[d]?g.push(a):f.push(a))},this);b(e,this);b(f,this);b(g,this)};e.prototype.fb=function(){return!!this.p.ha};e.prototype.zc=function(){var a=this.c("token"); +if(!this.fb()){var b=c.bind(function(b){return new C("__mpq_"+a+b.Ra,{A:this.config,Pc:c.bind(function(a,c,e){this.k(this.c("api_host")+b.C,this.Za(a),c,this.ab(e,a))},this),ea:c.bind(function(a){return this.cb("before_send_"+b.type,a)},this),I:this.c("error_reporter"),Zc:c.bind(this.Tb,this)})},this);this.p={ha:b({type:"events",C:"/track/",Ra:"_ev"}),Gc:b({type:"people",C:"/engage/",Ra:"_pp"}),yc:b({type:"groups",C:"/groups/",Ra:"_gr"})}}this.c("batch_autostart")&&this.Sb()};e.prototype.Sb=function(){if(this.fb())this.N= +m,c.a(this.p,function(a){a.start()})};e.prototype.Tb=function(){this.N=F;c.a(this.p,function(a){a.stop();a.clear()})};e.prototype.push=function(a){this.ua([a])};e.prototype.disable=function(a){"undefined"===typeof a?this.O.qc=m:this.ra=this.ra.concat(a)};e.prototype.Za=function(a){a=c.aa(a);"base64"===this.c("api_payload_format")&&(a=c.mc(a));return{data:a}};e.prototype.Aa=function(a,b){var d=c.truncate(a.data,255),e=a.C,f=a.Ca,g=a.Xc,i=a.Qc||{},b=b||O,h=m,k=c.bind(function(){i.Rb||(d=this.cb("before_send_"+ +a.type,d));return d?(p.log("MIXPANEL REQUEST:"),p.log(d),this.k(e,this.Za(d),i,this.ab(b,d))):q},this);this.N&&!g?f.Ha(d,function(a){a?b(1,d):k()}):h=k();return h&&d};e.prototype.m=P(function(a,b,d,e){!e&&"function"===typeof d&&(e=d,d=q);var d=d||{},f=d.transport;if(f)d.Ua=f;f=d.send_immediately;"function"!==typeof e&&(e=O);if(c.e(a))this.l("No event name provided to mixpanel.track");else if(this.$a(a))e(0);else{b=b||{};b.token=this.c("token");var g=this.persistence.Jc(a);c.e(g)||(b.$duration=parseFloat((((new Date).getTime()- +g)/1E3).toFixed(3)));this.eb();b=c.extend({},c.info.V(),this.persistence.V(),this.M,b);g=this.c("property_blacklist");c.isArray(g)?c.a(g,function(a){delete b[a]}):this.l("Invalid value for property_blacklist config: "+g);return this.Aa({type:"events",data:{event:a,properties:b},C:this.c("api_host")+"/track/",Ca:this.p.ha,Xc:f,Qc:d},e)}});e.prototype.Vc=P(function(a,b,d){c.isArray(b)||(b=[b]);var e={};e[a]=b;this.o(e);return this.people.set(a,b,d)});e.prototype.jc=P(function(a,b,c){var e=this.s(a); +if(e===l){var f={};f[a]=[b];this.o(f)}else-1===e.indexOf(b)&&(e.push(b),this.o(f));return this.people.Z(a,b,c)});e.prototype.Kc=P(function(a,b,c){var e=this.s(a);if(e!==l){var f=e.indexOf(b);-1(x.__SV||0)? +p.H("Version mismatch; please ensure you're using the latest version of the Mixpanel code snippet."):(c.a(x._i,function(a){a&&c.isArray(a)&&(G[a[a.length-1]]=U.apply(this,a))}),Ca(),x.init(),c.a(G,function(a){a.da()}),Ba())})()})(); })(); diff --git a/dist/mixpanel.umd.js b/dist/mixpanel.umd.js index 0b840751..8bb7419e 100644 --- a/dist/mixpanel.umd.js +++ b/dist/mixpanel.umd.js @@ -41,7 +41,7 @@ var hasOwnProperty = ObjProto.hasOwnProperty; var windowConsole = window$1.console; var navigator = window$1.navigator; - var document$1 = window$1.document; + var document = window$1.document; var windowOpera = window$1.opera; var screen = window$1.screen; var userAgent = navigator.userAgent; @@ -982,7 +982,7 @@ _.cookie = { get: function(name) { var nameEQ = name + '='; - var ca = document$1.cookie.split(';'); + var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { @@ -1013,7 +1013,7 @@ if (domain_override) { cdomain = '; domain=' + domain_override; } else if (is_cross_subdomain) { - var domain = extract_domain(document$1.location.hostname); + var domain = extract_domain(document.location.hostname); cdomain = domain ? '; domain=.' + domain : ''; } @@ -1031,7 +1031,7 @@ secure += '; secure'; } - document$1.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; + document.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; }, set: function(name, value, days, is_cross_subdomain, is_secure, is_cross_site, domain_override) { @@ -1040,7 +1040,7 @@ if (domain_override) { cdomain = '; domain=' + domain_override; } else if (is_cross_subdomain) { - var domain = extract_domain(document$1.location.hostname); + var domain = extract_domain(document.location.hostname); cdomain = domain ? '; domain=.' + domain : ''; } @@ -1059,7 +1059,7 @@ } var new_cookie_val = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; - document$1.cookie = new_cookie_val; + document.cookie = new_cookie_val; return new_cookie_val; }, @@ -1261,13 +1261,13 @@ function getElementsBySelector(selector) { // Attempt to fail gracefully in lesser browsers - if (!document$1.getElementsByTagName) { + if (!document.getElementsByTagName) { return []; } // Split selector in to tokens var tokens = selector.split(' '); var token, bits, tagName, found, foundCount, i, j, k, elements, currentContextIndex; - var currentContext = [document$1]; + var currentContext = [document]; for (i = 0; i < tokens.length; i++) { token = tokens[i].replace(/^\s+/, '').replace(/\s+$/, ''); if (token.indexOf('#') > -1) { @@ -1275,7 +1275,7 @@ bits = token.split('#'); tagName = bits[0]; var id = bits[1]; - var element = document$1.getElementById(id); + var element = document.getElementById(id); if (!element || (tagName && element.nodeName.toLowerCase() != tagName)) { // element not found or tag with that ID not found, return false return []; @@ -1422,7 +1422,7 @@ kw = '', params = {}; _.each(campaign_keywords, function(kwkey) { - kw = _.getQueryParam(document$1.URL, kwkey); + kw = _.getQueryParam(document.URL, kwkey); if (kw.length) { params[kwkey] = kw; } @@ -1603,8 +1603,8 @@ return _.extend(_.strip_empty_properties({ '$os': _.info.os(), '$browser': _.info.browser(userAgent, navigator.vendor, windowOpera), - '$referrer': document$1.referrer, - '$referring_domain': _.info.referringDomain(document$1.referrer), + '$referrer': document.referrer, + '$referring_domain': _.info.referringDomain(document.referrer), '$device': _.info.device(userAgent) }), { '$current_url': window$1.location.href, @@ -1630,7 +1630,7 @@ pageviewInfo: function(page) { return _.strip_empty_properties({ 'mp_page': page, - 'mp_referrer': document$1.referrer, + 'mp_referrer': document.referrer, 'mp_browser': _.info.browser(userAgent, navigator.vendor, windowOpera), 'mp_platform': _.info.os() }); @@ -4059,11 +4059,12 @@ // http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ // https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#withCredentials var USE_XHR = (window$1.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()); + var USE_FETCH = !_.isUndefined(fetch) && typeof(fetch) === 'function' // IE<10 does not support cross-origin XHR's but script tags // with defer won't block window.onload; ENQUEUE_REQUESTS // should only be true for Opera<12 - var ENQUEUE_REQUESTS = !USE_XHR && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); + var ENQUEUE_REQUESTS = !USE_XHR && !USE_FETCH && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); // save reference to navigator.sendBeacon so it can be minified var sendBeacon = null; @@ -4280,7 +4281,7 @@ } }); window$1.addEventListener('visibilitychange', function() { - if (document$1['visibilityState'] === 'hidden') { + if (document['visibilityState'] === 'hidden') { flush_on_unload(); } }); @@ -4313,12 +4314,12 @@ // update persistence with info on referrer, UTM params, etc MixpanelLib.prototype._set_default_superprops = function() { - this['persistence'].update_search_keyword(document$1.referrer); + this['persistence'].update_search_keyword(document.referrer); if (this.get_config('store_google')) { this['persistence'].update_campaign_params(); } if (this.get_config('save_referrer')) { - this['persistence'].update_referrer_info(document$1.referrer); + this['persistence'].update_referrer_info(document.referrer); } }; @@ -4366,7 +4367,7 @@ return null; } - if (USE_XHR) { + if (USE_XHR || USE_FETCH) { var callback_function = function(response) { callback(response, data); }; @@ -4406,7 +4407,7 @@ options = null; } options = _.extend(DEFAULT_OPTIONS, options || {}); - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { options.method = 'GET'; } var use_post = options.method === 'POST'; @@ -4419,7 +4420,7 @@ if (this.get_config('test')) { data['test'] = 1; } if (verbose_mode) { data['verbose'] = 1; } if (this.get_config('img')) { data['img'] = 1; } - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { if (callback) { data['callback'] = callback; } else if (verbose_mode || this.get_config('test')) { @@ -4443,9 +4444,9 @@ var lib = this; if ('img' in data) { - var img = document$1.createElement('img'); + var img = document.createElement('img'); img.src = url; - document$1.body.appendChild(img); + document.body.appendChild(img); } else if (use_sendBeacon) { try { succeeded = sendBeacon(url, body_data); @@ -4529,13 +4530,78 @@ lib.report_error(e); succeeded = false; } + } else if (USE_FETCH) { + try { + var headers = this.get_config('xhr_headers'); + if (use_post) { + headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + + var fetchOpts = { + method: options.method, + mode: 'cors', + credentials: 'include', + headers: headers, + body: body_data + }; + + fetch(url, fetchOpts) + .then(function (response) { + return response.text().then(function (body) { + return { + status: response.status, + statusText: response.statusText, + headers: response.headers, + body: body + }; + }); + }) + .then(function (res) { + if (res.status === 200) { + if (callback) { + var body = res.body; + if (verbose_mode) { + var response; + try { + response = _.JSONDecode(body); + } catch (e) { + lib.report_error(e); + if (options.ignore_json_errors) { + response = body; + } else { + return; + } + } + callback(response); + } else { + callback(Number(body)); + } + } + } else { + var error = 'Bad HTTP status: ' + res.status + ' ' + res.statusText; + lib.report_error(error); + + if (callback) { + if (verbose_mode) { + var xhr_req = { status: res.status, responseHeaders: res.headers }; + callback({ status: 0, error: error, xhr_req: xhr_req }); + } else { + callback(0); + } + } + } + }); + } catch (e) { + lib.report_error(e); + succeeded = false; + } } else { - var script = document$1.createElement('script'); + var script = document.createElement('script'); script.type = 'text/javascript'; script.async = true; script.defer = true; script.src = url; - var s = document$1.getElementsByTagName('script')[0]; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(script, s); } @@ -4972,7 +5038,7 @@ */ MixpanelLib.prototype.track_pageview = function(page) { if (_.isUndefined(page)) { - page = document$1.location.href; + page = document.location.href; } this.track('mp_page_view', _.info.pageviewInfo(page)); }; @@ -5929,7 +5995,7 @@ function do_scroll_check() { try { - document$1.documentElement.doScroll('left'); + document.documentElement.doScroll('left'); } catch(e) { setTimeout(do_scroll_check, 1); return; @@ -5938,19 +6004,19 @@ dom_loaded_handler(); } - if (document$1.addEventListener) { - if (document$1.readyState === 'complete') { + if (document.addEventListener) { + if (document.readyState === 'complete') { // safari 4 can fire the DOMContentLoaded event before loading all // external JS (including this file). you will see some copypasta // on the internet that checks for 'complete' and 'loaded', but // 'loaded' is an IE thing dom_loaded_handler(); } else { - document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false); + document.addEventListener('DOMContentLoaded', dom_loaded_handler, false); } - } else if (document$1.attachEvent) { + } else if (document.attachEvent) { // IE - document$1.attachEvent('onreadystatechange', dom_loaded_handler); + document.attachEvent('onreadystatechange', dom_loaded_handler); // check to make sure we arn't in a frame var toplevel = false; @@ -5960,7 +6026,7 @@ // noop } - if (document$1.documentElement.doScroll && toplevel) { + if (document.documentElement.doScroll && toplevel) { do_scroll_check(); } } diff --git a/examples/commonjs-browserify/bundle.js b/examples/commonjs-browserify/bundle.js index ae4fe5ad..d367e265 100644 --- a/examples/commonjs-browserify/bundle.js +++ b/examples/commonjs-browserify/bundle.js @@ -38,7 +38,7 @@ var toString = ObjProto.toString; var hasOwnProperty = ObjProto.hasOwnProperty; var windowConsole = window$1.console; var navigator = window$1.navigator; -var document$1 = window$1.document; +var document = window$1.document; var windowOpera = window$1.opera; var screen = window$1.screen; var userAgent = navigator.userAgent; @@ -979,7 +979,7 @@ _.getQueryParam = function(url, param) { _.cookie = { get: function(name) { var nameEQ = name + '='; - var ca = document$1.cookie.split(';'); + var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { @@ -1010,7 +1010,7 @@ _.cookie = { if (domain_override) { cdomain = '; domain=' + domain_override; } else if (is_cross_subdomain) { - var domain = extract_domain(document$1.location.hostname); + var domain = extract_domain(document.location.hostname); cdomain = domain ? '; domain=.' + domain : ''; } @@ -1028,7 +1028,7 @@ _.cookie = { secure += '; secure'; } - document$1.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; + document.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; }, set: function(name, value, days, is_cross_subdomain, is_secure, is_cross_site, domain_override) { @@ -1037,7 +1037,7 @@ _.cookie = { if (domain_override) { cdomain = '; domain=' + domain_override; } else if (is_cross_subdomain) { - var domain = extract_domain(document$1.location.hostname); + var domain = extract_domain(document.location.hostname); cdomain = domain ? '; domain=.' + domain : ''; } @@ -1056,7 +1056,7 @@ _.cookie = { } var new_cookie_val = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; - document$1.cookie = new_cookie_val; + document.cookie = new_cookie_val; return new_cookie_val; }, @@ -1258,13 +1258,13 @@ _.dom_query = (function() { function getElementsBySelector(selector) { // Attempt to fail gracefully in lesser browsers - if (!document$1.getElementsByTagName) { + if (!document.getElementsByTagName) { return []; } // Split selector in to tokens var tokens = selector.split(' '); var token, bits, tagName, found, foundCount, i, j, k, elements, currentContextIndex; - var currentContext = [document$1]; + var currentContext = [document]; for (i = 0; i < tokens.length; i++) { token = tokens[i].replace(/^\s+/, '').replace(/\s+$/, ''); if (token.indexOf('#') > -1) { @@ -1272,7 +1272,7 @@ _.dom_query = (function() { bits = token.split('#'); tagName = bits[0]; var id = bits[1]; - var element = document$1.getElementById(id); + var element = document.getElementById(id); if (!element || (tagName && element.nodeName.toLowerCase() != tagName)) { // element not found or tag with that ID not found, return false return []; @@ -1419,7 +1419,7 @@ _.info = { kw = '', params = {}; _.each(campaign_keywords, function(kwkey) { - kw = _.getQueryParam(document$1.URL, kwkey); + kw = _.getQueryParam(document.URL, kwkey); if (kw.length) { params[kwkey] = kw; } @@ -1600,8 +1600,8 @@ _.info = { return _.extend(_.strip_empty_properties({ '$os': _.info.os(), '$browser': _.info.browser(userAgent, navigator.vendor, windowOpera), - '$referrer': document$1.referrer, - '$referring_domain': _.info.referringDomain(document$1.referrer), + '$referrer': document.referrer, + '$referring_domain': _.info.referringDomain(document.referrer), '$device': _.info.device(userAgent) }), { '$current_url': window$1.location.href, @@ -1627,7 +1627,7 @@ _.info = { pageviewInfo: function(page) { return _.strip_empty_properties({ 'mp_page': page, - 'mp_referrer': document$1.referrer, + 'mp_referrer': document.referrer, 'mp_browser': _.info.browser(userAgent, navigator.vendor, windowOpera), 'mp_platform': _.info.os() }); @@ -4056,11 +4056,12 @@ var NOOP_FUNC = function() {}; // http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ // https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#withCredentials var USE_XHR = (window$1.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()); +var USE_FETCH = !_.isUndefined(fetch) && typeof(fetch) === 'function' // IE<10 does not support cross-origin XHR's but script tags // with defer won't block window.onload; ENQUEUE_REQUESTS // should only be true for Opera<12 -var ENQUEUE_REQUESTS = !USE_XHR && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); +var ENQUEUE_REQUESTS = !USE_XHR && !USE_FETCH && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); // save reference to navigator.sendBeacon so it can be minified var sendBeacon = null; @@ -4277,7 +4278,7 @@ MixpanelLib.prototype._init = function(token, config, name) { } }); window$1.addEventListener('visibilitychange', function() { - if (document$1['visibilityState'] === 'hidden') { + if (document['visibilityState'] === 'hidden') { flush_on_unload(); } }); @@ -4310,12 +4311,12 @@ MixpanelLib.prototype._loaded = function() { // update persistence with info on referrer, UTM params, etc MixpanelLib.prototype._set_default_superprops = function() { - this['persistence'].update_search_keyword(document$1.referrer); + this['persistence'].update_search_keyword(document.referrer); if (this.get_config('store_google')) { this['persistence'].update_campaign_params(); } if (this.get_config('save_referrer')) { - this['persistence'].update_referrer_info(document$1.referrer); + this['persistence'].update_referrer_info(document.referrer); } }; @@ -4363,7 +4364,7 @@ MixpanelLib.prototype._prepare_callback = function(callback, data) { return null; } - if (USE_XHR) { + if (USE_XHR || USE_FETCH) { var callback_function = function(response) { callback(response, data); }; @@ -4403,7 +4404,7 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) { options = null; } options = _.extend(DEFAULT_OPTIONS, options || {}); - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { options.method = 'GET'; } var use_post = options.method === 'POST'; @@ -4416,7 +4417,7 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) { if (this.get_config('test')) { data['test'] = 1; } if (verbose_mode) { data['verbose'] = 1; } if (this.get_config('img')) { data['img'] = 1; } - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { if (callback) { data['callback'] = callback; } else if (verbose_mode || this.get_config('test')) { @@ -4440,9 +4441,9 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) { var lib = this; if ('img' in data) { - var img = document$1.createElement('img'); + var img = document.createElement('img'); img.src = url; - document$1.body.appendChild(img); + document.body.appendChild(img); } else if (use_sendBeacon) { try { succeeded = sendBeacon(url, body_data); @@ -4526,13 +4527,78 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) { lib.report_error(e); succeeded = false; } + } else if (USE_FETCH) { + try { + var headers = this.get_config('xhr_headers'); + if (use_post) { + headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + + var fetchOpts = { + method: options.method, + mode: 'cors', + credentials: 'include', + headers: headers, + body: body_data + }; + + fetch(url, fetchOpts) + .then(function (response) { + return response.text().then(function (body) { + return { + status: response.status, + statusText: response.statusText, + headers: response.headers, + body: body + }; + }); + }) + .then(function (res) { + if (res.status === 200) { + if (callback) { + var body = res.body; + if (verbose_mode) { + var response; + try { + response = _.JSONDecode(body); + } catch (e) { + lib.report_error(e); + if (options.ignore_json_errors) { + response = body; + } else { + return; + } + } + callback(response); + } else { + callback(Number(body)); + } + } + } else { + var error = 'Bad HTTP status: ' + res.status + ' ' + res.statusText; + lib.report_error(error); + + if (callback) { + if (verbose_mode) { + var xhr_req = { status: res.status, responseHeaders: res.headers }; + callback({ status: 0, error: error, xhr_req: xhr_req }); + } else { + callback(0); + } + } + } + }); + } catch (e) { + lib.report_error(e); + succeeded = false; + } } else { - var script = document$1.createElement('script'); + var script = document.createElement('script'); script.type = 'text/javascript'; script.async = true; script.defer = true; script.src = url; - var s = document$1.getElementsByTagName('script')[0]; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(script, s); } @@ -4969,7 +5035,7 @@ MixpanelLib.prototype.get_group = function (group_key, group_id) { */ MixpanelLib.prototype.track_pageview = function(page) { if (_.isUndefined(page)) { - page = document$1.location.href; + page = document.location.href; } this.track('mp_page_view', _.info.pageviewInfo(page)); }; @@ -5926,7 +5992,7 @@ var add_dom_loaded_handler = function() { function do_scroll_check() { try { - document$1.documentElement.doScroll('left'); + document.documentElement.doScroll('left'); } catch(e) { setTimeout(do_scroll_check, 1); return; @@ -5935,19 +6001,19 @@ var add_dom_loaded_handler = function() { dom_loaded_handler(); } - if (document$1.addEventListener) { - if (document$1.readyState === 'complete') { + if (document.addEventListener) { + if (document.readyState === 'complete') { // safari 4 can fire the DOMContentLoaded event before loading all // external JS (including this file). you will see some copypasta // on the internet that checks for 'complete' and 'loaded', but // 'loaded' is an IE thing dom_loaded_handler(); } else { - document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false); + document.addEventListener('DOMContentLoaded', dom_loaded_handler, false); } - } else if (document$1.attachEvent) { + } else if (document.attachEvent) { // IE - document$1.attachEvent('onreadystatechange', dom_loaded_handler); + document.attachEvent('onreadystatechange', dom_loaded_handler); // check to make sure we arn't in a frame var toplevel = false; @@ -5957,7 +6023,7 @@ var add_dom_loaded_handler = function() { // noop } - if (document$1.documentElement.doScroll && toplevel) { + if (document.documentElement.doScroll && toplevel) { do_scroll_check(); } } diff --git a/examples/es2015-babelify/bundle.js b/examples/es2015-babelify/bundle.js index afea9244..4d6bbba2 100644 --- a/examples/es2015-babelify/bundle.js +++ b/examples/es2015-babelify/bundle.js @@ -737,11 +737,12 @@ var NOOP_FUNC = function NOOP_FUNC() {}; // http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ // https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#withCredentials var USE_XHR = _utils.window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest(); +var USE_FETCH = !_utils._.isUndefined(fetch) && typeof fetch === 'function'; // IE<10 does not support cross-origin XHR's but script tags // with defer won't block window.onload; ENQUEUE_REQUESTS // should only be true for Opera<12 -var ENQUEUE_REQUESTS = !USE_XHR && _utils.userAgent.indexOf('MSIE') === -1 && _utils.userAgent.indexOf('Mozilla') === -1; +var ENQUEUE_REQUESTS = !USE_XHR && !USE_FETCH && _utils.userAgent.indexOf('MSIE') === -1 && _utils.userAgent.indexOf('Mozilla') === -1; // save reference to navigator.sendBeacon so it can be minified var sendBeacon = null; @@ -1043,7 +1044,7 @@ MixpanelLib.prototype._prepare_callback = function (callback, data) { return null; } - if (USE_XHR) { + if (USE_XHR || USE_FETCH) { var callback_function = function callback_function(response) { callback(response, data); }; @@ -1083,7 +1084,7 @@ MixpanelLib.prototype._send_request = function (url, data, options, callback) { options = null; } options = _utils._.extend(DEFAULT_OPTIONS, options || {}); - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { options.method = 'GET'; } var use_post = options.method === 'POST'; @@ -1104,7 +1105,7 @@ MixpanelLib.prototype._send_request = function (url, data, options, callback) { if (this.get_config('img')) { data['img'] = 1; } - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { if (callback) { data['callback'] = callback; } else if (verbose_mode || this.get_config('test')) { @@ -1211,6 +1212,69 @@ MixpanelLib.prototype._send_request = function (url, data, options, callback) { lib.report_error(e); succeeded = false; } + } else if (USE_FETCH) { + try { + var headers = this.get_config('xhr_headers'); + if (use_post) { + headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + + var fetchOpts = { + method: options.method, + mode: 'cors', + credentials: 'include', + headers: headers, + body: body_data + }; + + fetch(url, fetchOpts).then(function (response) { + return response.text().then(function (body) { + return { + status: response.status, + statusText: response.statusText, + headers: response.headers, + body: body + }; + }); + }).then(function (res) { + if (res.status === 200) { + if (callback) { + var body = res.body; + if (verbose_mode) { + var response; + try { + response = _utils._.JSONDecode(body); + } catch (e) { + lib.report_error(e); + if (options.ignore_json_errors) { + response = body; + } else { + return; + } + } + callback(response); + } else { + callback(Number(body)); + } + } + } else { + var error = 'Bad HTTP status: ' + res.status + ' ' + res.statusText; + lib.report_error(error); + + if (callback) { + if (verbose_mode) { + var xhr_req = { status: res.status, responseHeaders: res.headers }; + callback({ status: 0, error: error, xhr_req: xhr_req }); + } else { + callback(0); + } + } + } + }); + } catch (e) { + lib.report_error(e); + succeeded = false; + } } else { var script = _utils.document.createElement('script'); script.type = 'text/javascript'; @@ -2919,7 +2983,7 @@ MixpanelPeople.prototype.set = (0, _gdprUtils.addOptOutCheckMixpanelPeople)(func } // make sure that the referrer info has been updated and saved if (this._get_config('save_referrer')) { - this._mixpanel['persistence'].update_referrer_info(document.referrer); + this._mixpanel['persistence'].update_referrer_info(_utils.document.referrer); } // update $set object with default people properties diff --git a/examples/umd-webpack/bundle.js b/examples/umd-webpack/bundle.js index 29d68e8d..b00319bd 100644 --- a/examples/umd-webpack/bundle.js +++ b/examples/umd-webpack/bundle.js @@ -104,7 +104,7 @@ var hasOwnProperty = ObjProto.hasOwnProperty; var windowConsole = window$1.console; var navigator = window$1.navigator; - var document$1 = window$1.document; + var document = window$1.document; var windowOpera = window$1.opera; var screen = window$1.screen; var userAgent = navigator.userAgent; @@ -1045,7 +1045,7 @@ _.cookie = { get: function(name) { var nameEQ = name + '='; - var ca = document$1.cookie.split(';'); + var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { @@ -1076,7 +1076,7 @@ if (domain_override) { cdomain = '; domain=' + domain_override; } else if (is_cross_subdomain) { - var domain = extract_domain(document$1.location.hostname); + var domain = extract_domain(document.location.hostname); cdomain = domain ? '; domain=.' + domain : ''; } @@ -1094,7 +1094,7 @@ secure += '; secure'; } - document$1.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; + document.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; }, set: function(name, value, days, is_cross_subdomain, is_secure, is_cross_site, domain_override) { @@ -1103,7 +1103,7 @@ if (domain_override) { cdomain = '; domain=' + domain_override; } else if (is_cross_subdomain) { - var domain = extract_domain(document$1.location.hostname); + var domain = extract_domain(document.location.hostname); cdomain = domain ? '; domain=.' + domain : ''; } @@ -1122,7 +1122,7 @@ } var new_cookie_val = name + '=' + encodeURIComponent(value) + expires + '; path=/' + cdomain + secure; - document$1.cookie = new_cookie_val; + document.cookie = new_cookie_val; return new_cookie_val; }, @@ -1324,13 +1324,13 @@ function getElementsBySelector(selector) { // Attempt to fail gracefully in lesser browsers - if (!document$1.getElementsByTagName) { + if (!document.getElementsByTagName) { return []; } // Split selector in to tokens var tokens = selector.split(' '); var token, bits, tagName, found, foundCount, i, j, k, elements, currentContextIndex; - var currentContext = [document$1]; + var currentContext = [document]; for (i = 0; i < tokens.length; i++) { token = tokens[i].replace(/^\s+/, '').replace(/\s+$/, ''); if (token.indexOf('#') > -1) { @@ -1338,7 +1338,7 @@ bits = token.split('#'); tagName = bits[0]; var id = bits[1]; - var element = document$1.getElementById(id); + var element = document.getElementById(id); if (!element || (tagName && element.nodeName.toLowerCase() != tagName)) { // element not found or tag with that ID not found, return false return []; @@ -1485,7 +1485,7 @@ kw = '', params = {}; _.each(campaign_keywords, function(kwkey) { - kw = _.getQueryParam(document$1.URL, kwkey); + kw = _.getQueryParam(document.URL, kwkey); if (kw.length) { params[kwkey] = kw; } @@ -1666,8 +1666,8 @@ return _.extend(_.strip_empty_properties({ '$os': _.info.os(), '$browser': _.info.browser(userAgent, navigator.vendor, windowOpera), - '$referrer': document$1.referrer, - '$referring_domain': _.info.referringDomain(document$1.referrer), + '$referrer': document.referrer, + '$referring_domain': _.info.referringDomain(document.referrer), '$device': _.info.device(userAgent) }), { '$current_url': window$1.location.href, @@ -1693,7 +1693,7 @@ pageviewInfo: function(page) { return _.strip_empty_properties({ 'mp_page': page, - 'mp_referrer': document$1.referrer, + 'mp_referrer': document.referrer, 'mp_browser': _.info.browser(userAgent, navigator.vendor, windowOpera), 'mp_platform': _.info.os() }); @@ -4122,11 +4122,12 @@ // http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ // https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#withCredentials var USE_XHR = (window$1.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()); + var USE_FETCH = !_.isUndefined(fetch) && typeof(fetch) === 'function' // IE<10 does not support cross-origin XHR's but script tags // with defer won't block window.onload; ENQUEUE_REQUESTS // should only be true for Opera<12 - var ENQUEUE_REQUESTS = !USE_XHR && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); + var ENQUEUE_REQUESTS = !USE_XHR && !USE_FETCH && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); // save reference to navigator.sendBeacon so it can be minified var sendBeacon = null; @@ -4343,7 +4344,7 @@ } }); window$1.addEventListener('visibilitychange', function() { - if (document$1['visibilityState'] === 'hidden') { + if (document['visibilityState'] === 'hidden') { flush_on_unload(); } }); @@ -4376,12 +4377,12 @@ // update persistence with info on referrer, UTM params, etc MixpanelLib.prototype._set_default_superprops = function() { - this['persistence'].update_search_keyword(document$1.referrer); + this['persistence'].update_search_keyword(document.referrer); if (this.get_config('store_google')) { this['persistence'].update_campaign_params(); } if (this.get_config('save_referrer')) { - this['persistence'].update_referrer_info(document$1.referrer); + this['persistence'].update_referrer_info(document.referrer); } }; @@ -4429,7 +4430,7 @@ return null; } - if (USE_XHR) { + if (USE_XHR || USE_FETCH) { var callback_function = function(response) { callback(response, data); }; @@ -4469,7 +4470,7 @@ options = null; } options = _.extend(DEFAULT_OPTIONS, options || {}); - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { options.method = 'GET'; } var use_post = options.method === 'POST'; @@ -4482,7 +4483,7 @@ if (this.get_config('test')) { data['test'] = 1; } if (verbose_mode) { data['verbose'] = 1; } if (this.get_config('img')) { data['img'] = 1; } - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { if (callback) { data['callback'] = callback; } else if (verbose_mode || this.get_config('test')) { @@ -4506,9 +4507,9 @@ var lib = this; if ('img' in data) { - var img = document$1.createElement('img'); + var img = document.createElement('img'); img.src = url; - document$1.body.appendChild(img); + document.body.appendChild(img); } else if (use_sendBeacon) { try { succeeded = sendBeacon(url, body_data); @@ -4592,13 +4593,78 @@ lib.report_error(e); succeeded = false; } + } else if (USE_FETCH) { + try { + var headers = this.get_config('xhr_headers'); + if (use_post) { + headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + + var fetchOpts = { + method: options.method, + mode: 'cors', + credentials: 'include', + headers: headers, + body: body_data + }; + + fetch(url, fetchOpts) + .then(function (response) { + return response.text().then(function (body) { + return { + status: response.status, + statusText: response.statusText, + headers: response.headers, + body: body + }; + }); + }) + .then(function (res) { + if (res.status === 200) { + if (callback) { + var body = res.body; + if (verbose_mode) { + var response; + try { + response = _.JSONDecode(body); + } catch (e) { + lib.report_error(e); + if (options.ignore_json_errors) { + response = body; + } else { + return; + } + } + callback(response); + } else { + callback(Number(body)); + } + } + } else { + var error = 'Bad HTTP status: ' + res.status + ' ' + res.statusText; + lib.report_error(error); + + if (callback) { + if (verbose_mode) { + var xhr_req = { status: res.status, responseHeaders: res.headers }; + callback({ status: 0, error: error, xhr_req: xhr_req }); + } else { + callback(0); + } + } + } + }); + } catch (e) { + lib.report_error(e); + succeeded = false; + } } else { - var script = document$1.createElement('script'); + var script = document.createElement('script'); script.type = 'text/javascript'; script.async = true; script.defer = true; script.src = url; - var s = document$1.getElementsByTagName('script')[0]; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(script, s); } @@ -5035,7 +5101,7 @@ */ MixpanelLib.prototype.track_pageview = function(page) { if (_.isUndefined(page)) { - page = document$1.location.href; + page = document.location.href; } this.track('mp_page_view', _.info.pageviewInfo(page)); }; @@ -5992,7 +6058,7 @@ function do_scroll_check() { try { - document$1.documentElement.doScroll('left'); + document.documentElement.doScroll('left'); } catch(e) { setTimeout(do_scroll_check, 1); return; @@ -6001,19 +6067,19 @@ dom_loaded_handler(); } - if (document$1.addEventListener) { - if (document$1.readyState === 'complete') { + if (document.addEventListener) { + if (document.readyState === 'complete') { // safari 4 can fire the DOMContentLoaded event before loading all // external JS (including this file). you will see some copypasta // on the internet that checks for 'complete' and 'loaded', but // 'loaded' is an IE thing dom_loaded_handler(); } else { - document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false); + document.addEventListener('DOMContentLoaded', dom_loaded_handler, false); } - } else if (document$1.attachEvent) { + } else if (document.attachEvent) { // IE - document$1.attachEvent('onreadystatechange', dom_loaded_handler); + document.attachEvent('onreadystatechange', dom_loaded_handler); // check to make sure we arn't in a frame var toplevel = false; @@ -6023,7 +6089,7 @@ // noop } - if (document$1.documentElement.doScroll && toplevel) { + if (document.documentElement.doScroll && toplevel) { do_scroll_check(); } } diff --git a/src/mixpanel-core.js b/src/mixpanel-core.js index 73119a77..b0bb2402 100644 --- a/src/mixpanel-core.js +++ b/src/mixpanel-core.js @@ -65,11 +65,12 @@ var NOOP_FUNC = function() {}; // http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ // https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#withCredentials var USE_XHR = (window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()); +var USE_FETCH = !_.isUndefined(fetch) && typeof(fetch) === 'function' // IE<10 does not support cross-origin XHR's but script tags // with defer won't block window.onload; ENQUEUE_REQUESTS // should only be true for Opera<12 -var ENQUEUE_REQUESTS = !USE_XHR && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); +var ENQUEUE_REQUESTS = !USE_XHR && !USE_FETCH && (userAgent.indexOf('MSIE') === -1) && (userAgent.indexOf('Mozilla') === -1); // save reference to navigator.sendBeacon so it can be minified var sendBeacon = null; @@ -372,7 +373,7 @@ MixpanelLib.prototype._prepare_callback = function(callback, data) { return null; } - if (USE_XHR) { + if (USE_XHR || USE_FETCH) { var callback_function = function(response) { callback(response, data); }; @@ -412,7 +413,7 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) { options = null; } options = _.extend(DEFAULT_OPTIONS, options || {}); - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { options.method = 'GET'; } var use_post = options.method === 'POST'; @@ -425,7 +426,7 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) { if (this.get_config('test')) { data['test'] = 1; } if (verbose_mode) { data['verbose'] = 1; } if (this.get_config('img')) { data['img'] = 1; } - if (!USE_XHR) { + if (!USE_XHR && !USE_FETCH) { if (callback) { data['callback'] = callback; } else if (verbose_mode || this.get_config('test')) { @@ -535,6 +536,71 @@ MixpanelLib.prototype._send_request = function(url, data, options, callback) { lib.report_error(e); succeeded = false; } + } else if (USE_FETCH) { + try { + var headers = this.get_config('xhr_headers'); + if (use_post) { + headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + + var fetchOpts = { + method: options.method, + mode: 'cors', + credentials: 'include', + headers: headers, + body: body_data + }; + + fetch(url, fetchOpts) + .then(function (response) { + return response.text().then(function (body) { + return { + status: response.status, + statusText: response.statusText, + headers: response.headers, + body: body + }; + }); + }) + .then(function (res) { + if (res.status === 200) { + if (callback) { + var body = res.body; + if (verbose_mode) { + var response; + try { + response = _.JSONDecode(body); + } catch (e) { + lib.report_error(e); + if (options.ignore_json_errors) { + response = body; + } else { + return; + } + } + callback(response); + } else { + callback(Number(body)); + } + } + } else { + var error = 'Bad HTTP status: ' + res.status + ' ' + res.statusText; + lib.report_error(error); + + if (callback) { + if (verbose_mode) { + var xhr_req = { status: res.status, responseHeaders: res.headers }; + callback({ status: 0, error: error, xhr_req: xhr_req }); + } else { + callback(0); + } + } + } + }); + } catch (e) { + lib.report_error(e); + succeeded = false; + } } else { var script = document.createElement('script'); script.type = 'text/javascript'; diff --git a/src/mixpanel-people.js b/src/mixpanel-people.js index 4fc666eb..a1e31d45 100644 --- a/src/mixpanel-people.js +++ b/src/mixpanel-people.js @@ -10,7 +10,7 @@ import { UNION_ACTION, apiActions } from './api-actions'; -import { _, console } from './utils'; +import { _, console, document } from './utils'; /** * Mixpanel People Object