{"version":3,"sources":["node_modules/browserify/node_modules/browser-pack/_prelude.js","network.js","../lib/EventDispatcher.js","../lib/Http/BandwidthModule.js","../lib/Http/HttpModule.js","../lib/Http/LatencyModule.js","../lib/Network.js","../lib/Timing.js","../utils/helpers.js"],"names":["f","exports","module","define","amd","g","window","global","self","this","Network","e","t","n","r","s","o","u","a","require","i","Error","code","l","call","length",1,"_classCallCheck","instance","Constructor","TypeError","Object","defineProperty","value","_createClass","defineProperties","target","props","descriptor","enumerable","configurable","writable","key","protoProps","staticProps","prototype","EventDispatcher","_eventCallbacks","events","callback","_this","Array","isArray","forEach","event","eventCallbacks","indexOf","push","_this2","undefined","arguments","callbackIndex","splice","_len","extraParameters","_key","returnValue","eventCallback","apply",2,"_interopRequireDefault","obj","__esModule","default","_inherits","subClass","superClass","create","constructor","__proto__","_get","_x2","_x3","_x4","_again","object","property","receiver","desc","parent","getter","Function","getOwnPropertyDescriptor","get","getPrototypeOf","_HttpModule2","_HttpModule3","_Timing","_Timing2","_utilsHelpers","BandwidthModule","_HttpModule","loadingType","settings","_extendDefaultSettings","data","size","multiplier","_loadingType","_intendedEnd","_isRestarting","_lastLoadedValue","_speedRecords","_avgSpeed","_requestID","_progressID","_started","_firstProgress","_deferredProgress","_timingLabels","start","progress","end","measure","on","mark","xhr","readyState","XMLHttpRequest","LOADING","eventsPrefix","_progress","_timeout","_end","dataSettings","reqID","defer","trigger","labels","blob","Blob","ArrayBuffer","type","_newRequest","_sendRequest","_abort","run","progressID","markLabel","loaded","instantSpeed","avgMeasure","avgSpeed","instantMeasure","../../utils/helpers","../Timing","./HttpModule",3,"_x5","_x6","_EventDispatcher2","_EventDispatcher3","HttpModule","_EventDispatcher","moduleName","endpoint","delay","_moduleName","_xhr","_lastURLToken","_requestingOverridden","_requesting","_settings","isObject","assignStrict","_defaultSettings","assign","httpMethod","queryParams","console","warn","validHttpMethods","tokenSuffix","Date","getTime","url","keys","param","encodeURIComponent","open","OPENED","abort","eventType","addEventListener","args","concat","upload","_len2","_key2","startTimeout","setTimeout","timeoutStarted","send","lastURLToken","entries","performance","getEntriesByType","filter","entry","name","isRequesting","../EventDispatcher",4,"_x7","LatencyModule","measures","attempts","_requestsLeft","_attemptsLeft","_latencies","supportsResourceTiming","_measure","except","_settings2","_setRequesting","_nextRequest","retry","requestsLeft","_this3","HEADERS_RECEIVED","latency","_getTimingEntry","secureConnectionStart","connectStart","connectEnd","latencies","avgLatency","reduce","b","_settings3","join",5,"_defineProperty","_HttpHttpModule","_HttpHttpModule2","_HttpLatencyModule","_HttpLatencyModule2","_HttpBandwidthModule","_HttpBandwidthModule2","_modules","_modulesInitialized","_pendingSettings","_registerModule","_initModules","moduleNames","_ret","globalSettings","localSettings","v","requesting","_name","hasOwnProperty","moduleCallback","getGlobalObject","classes","Timing","../utils/helpers","./EventDispatcher","./Http/BandwidthModule","./Http/HttpModule","./Http/LatencyModule","./Timing",6,"_support","userTiming","resourceTiming","timing","_marks","_measures","label","support","marks","now","measureLabel","markLabelA","markLabelB","measureWithoutUserTiming","entriesByName","getEntriesByName","duration",7,"valueOf","copy","JSON","parse","stringify","_assign","strict","sources","source","_len3","_key3","properties","objCopy","index","func","_class"],"mappings":"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","file":"network.min.js","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n extraParameters[_key - 1] = arguments[_key];\n }\n\n var eventCallbacks = this._eventCallbacks[event] || [];\n\n // A callback can return a boolean value which will be logically compared to the other callbacks values before\n // being returned by the trigger() method. This allows a callback to send a \"signal\" to the caller, like\n // cancelling an action.\n var returnValue = true;\n\n eventCallbacks.forEach(function (eventCallback) {\n // A callback must explicitly return false if it wants the trigger() method to return false, undefined will\n // not work. This avoids crappy callbacks to mess up with the triggering system.\n var value = eventCallback.apply(undefined, extraParameters);\n value = value !== false ? true : false;\n\n returnValue = returnValue && value; // Compare the result of the callback to the actual return value\n });\n\n return returnValue;\n }\n }]);\n\n return EventDispatcher;\n})();\n\nexports[\"default\"] = EventDispatcher;\nmodule.exports = exports[\"default\"];\n\n},{}],2:[function(require,module,exports){\n'use strict';\n\nObject.defineProperty(exports, '__esModule', {\n value: true\n});\n\nvar _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();\n\nvar _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }\n\nvar _HttpModule2 = require('./HttpModule');\n\nvar _HttpModule3 = _interopRequireDefault(_HttpModule2);\n\nvar _Timing = require('../Timing');\n\nvar _Timing2 = _interopRequireDefault(_Timing);\n\nvar _utilsHelpers = require('../../utils/helpers');\n\n/**\n * @public\n * @typedef {Object} BandwidthModule~settingsObject\n * @extends HttpModule~settingsObject\n * @property {Object} data\n * @property {number} data.size The amount of data to initially use.\n * @property {number} [data.multiplier=2] If the measure period can't reach the delay defined in the settings, the data amount is multiplied by the following value.\n */\n\n/**\n * Apply a new set of custom settings.\n * @public\n * @method BandwidthModule#settings\n * @param {BandwidthModule~settingsObject} settings A set of custom settings.\n * @returns {BandwidthModule}\n */\n/**\n * Return the current set of settings.\n * @public\n * @method BandwidthModule#settings^2\n * @returns {BandwidthModule~settingsObject}\n */\n\n/**\n * @class BandwidthModule\n * @extends HttpModule\n * @param {string} loadingType The loading type, `upload` or `download`.\n * @param {BandwidthModule~settingsObject} [settings={}] A set of custom settings.\n */\n\nvar BandwidthModule = (function (_HttpModule) {\n function BandwidthModule(loadingType) {\n var _this = this;\n\n var settings = arguments[1] === undefined ? {} : arguments[1];\n\n _classCallCheck(this, BandwidthModule);\n\n loadingType = ~['upload', 'download'].indexOf(loadingType) ? loadingType : 'download';\n\n _get(Object.getPrototypeOf(BandwidthModule.prototype), 'constructor', this).call(this, loadingType);\n\n this._extendDefaultSettings({\n data: {\n // 2 MB for upload, 10 MB for download\n size: loadingType == 'upload' ? 2 * 1024 * 1024 : 10 * 1024 * 1024,\n multiplier: 2\n }\n }).settings(settings);\n\n // Define the object properties\n this._loadingType = loadingType;\n\n this._intendedEnd = false;\n this._isRestarting = false;\n\n this._lastLoadedValue = null;\n this._speedRecords = [];\n this._avgSpeed = null;\n\n this._requestID = 0;\n this._progressID = 0;\n\n this._started = false;\n this._firstProgress = true;\n this._deferredProgress;\n\n // Unique labels for each request, exclusively used to make measures.\n this._timingLabels = {\n start: null,\n progress: null,\n end: null,\n measure: null\n };\n\n // Bind to XHR events\n this.on('xhr-upload-loadstart', function () {\n return _Timing2['default'].mark(_this._timingLabels.start);\n });\n this.on('xhr-readystatechange', function (xhr) {\n if (!_this._started && xhr.readyState == XMLHttpRequest.LOADING) {\n _Timing2['default'].mark(_this._timingLabels.start);\n _this._started = true;\n }\n });\n\n var eventsPrefix = loadingType == 'upload' ? 'xhr-upload' : 'xhr';\n\n this.on(eventsPrefix + '-progress', function (xhr, event) {\n return _this._progress(event);\n });\n this.on(eventsPrefix + '-timeout', function () {\n return _this._timeout();\n });\n this.on(eventsPrefix + '-loadend', function () {\n return _this._end();\n });\n }\n\n _inherits(BandwidthModule, _HttpModule);\n\n _createClass(BandwidthModule, [{\n key: 'start',\n\n /**\n * Start requesting the server to make measures.\n * @public\n * @method BandwidthModule#start\n * @returns {BandwidthModule}\n */\n value: function start() {\n var loadingType = this._loadingType,\n dataSettings = this.settings().data,\n reqID = this._requestID++;\n\n this._intendedEnd = false;\n this._lastLoadedValue = null;\n this._speedRecords = [];\n this._started = false;\n this._firstProgress = true;\n this._deferredProgress = (0, _utilsHelpers.defer)();\n\n // Trigger the start event\n if (!this._isRestarting) {\n this.trigger('start', dataSettings.size);\n }\n\n // Create unique timing labels for the new request\n var labels = this._timingLabels;\n labels.start = loadingType + '-' + reqID + '-start';\n labels.progress = loadingType + '-' + reqID + '-progress';\n labels.end = loadingType + '-' + reqID + '-end';\n labels.measure = loadingType + '-' + reqID + '-measure';\n\n // Generate some random data to upload to the server. Here we're using a Blob instead of an ArrayBuffer because\n // of a bug in Chrome (tested in v33.0.1750.146), causing a freeze of the page while trying to directly upload\n // an ArrayBuffer (through an ArrayBufferView). The freeze lasts nearly 4.5s for 10MB of data. Using a Blob\n // seems to solve the problem.\n var blob = loadingType == 'upload' ? new Blob([new ArrayBuffer(dataSettings.size)]) : null;\n\n var type = loadingType == 'download' ? 'GET' : 'POST';\n\n // Initiate and send a new request\n this._newRequest(type, {\n size: dataSettings.size\n })._sendRequest(blob);\n\n return this;\n }\n }, {\n key: 'abort',\n\n /**\n * Abort the measures.\n * @public\n * @method BandwidthModule#abort\n * @returns {BandwidthModule}\n */\n value: function abort() {\n this._intendedEnd = true;\n return this._abort();\n }\n }, {\n key: '_progress',\n\n /**\n * Make bandwidth measures for the current request.\n * @private\n * @method BandwidthModule#_progress\n * @param {ProgressEvent} event The event associated with the progress event of the current request.\n * @returns {BandwidthModule}\n */\n value: function _progress(event) {\n var _this2 = this;\n\n // Ignore the first progress event, it generally contributes to get incoherent values.\n if (this._firstProgress) return this._firstProgress = false;\n\n // Execute the previous progress trigger\n this._deferredProgress.run();\n\n var labels = this._timingLabels,\n progressID = this._progressID++,\n markLabel = labels.progress + '-' + progressID,\n loaded = event.loaded;\n\n _Timing2['default'].mark(markLabel);\n\n // Measure the average speed (B/s) since the request started\n var avgMeasure = _Timing2['default'].measure(labels.measure + '-avg-' + progressID, labels.start, markLabel),\n avgSpeed = loaded / avgMeasure * 1000;\n\n var instantSpeed;\n\n if (!this._lastLoadedValue) {\n // We are executing the first progress event of the current request\n instantSpeed = avgSpeed; // The instant speed of the first progress event is equal to the average one\n } else {\n // Measure the instant speed (B/s), which defines the speed between two progress events.\n var instantMeasure = _Timing2['default'].measure(labels.measure + '-instant-' + progressID,\n // Set the mark of the previous progress event as the starting point\n labels.progress + '-' + (progressID - 1), markLabel);\n instantSpeed = (loaded - this._lastLoadedValue) / instantMeasure * 1000;\n }\n\n // Save the `loaded` property of the event for the next progress event\n this._lastLoadedValue = loaded;\n\n // Defer measures saving and event triggering, this allows to cancel the last progress event, which can generate\n // incoherent values.\n this._deferredProgress = (0, _utilsHelpers.defer)(function () {\n _this2._avgSpeed = avgSpeed;\n _this2._speedRecords.push(instantSpeed);\n\n _this2.trigger('progress', avgSpeed, instantSpeed);\n });\n\n return this;\n }\n }, {\n key: '_timeout',\n\n /**\n * Mark the current request as entirely finished (this means it ended after a time out).\n * @private\n * @method BandwidthModule#_timeout\n * @returns {BandwidthModule}\n */\n value: function _timeout() {\n this._intendedEnd = true;\n return this;\n }\n }, {\n key: '_end',\n\n /**\n * End the measures.\n * @private\n * @method BandwidthModule#_end\n * @returns {BandwidthModule}\n */\n value: function _end() {\n // A timeout or an abort occured, bypass the further requests and trigger the \"end\" event.\n if (this._intendedEnd) {\n this._isRestarting = false;\n this.trigger('end', this._avgSpeed, this._speedRecords);\n }\n\n // The request ended to early, restart it with an increased data size.\n else {\n var loadingType = this._loadingType,\n dataSettings = this.settings().data;\n\n dataSettings.size *= dataSettings.multiplier;\n\n this.trigger('restart', dataSettings.size);\n\n this._isRestarting = true;\n this.start();\n }\n\n return this;\n }\n }]);\n\n return BandwidthModule;\n})(_HttpModule3['default']);\n\nexports['default'] = BandwidthModule;\nmodule.exports = exports['default'];\n\n},{\"../../utils/helpers\":7,\"../Timing\":6,\"./HttpModule\":3}],3:[function(require,module,exports){\n'use strict';\n\nObject.defineProperty(exports, '__esModule', {\n value: true\n});\n\nvar _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();\n\nvar _get = function get(_x4, _x5, _x6) { var _again = true; _function: while (_again) { var object = _x4, property = _x5, receiver = _x6; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x4 = parent; _x5 = property; _x6 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }\n\nvar _EventDispatcher2 = require('../EventDispatcher');\n\nvar _EventDispatcher3 = _interopRequireDefault(_EventDispatcher2);\n\nvar _utilsHelpers = require('../../utils/helpers');\n\n/**\n * @public\n * @typedef {Object} HttpModule~settingsObject\n * @property {string} [endpoint=./network.php] Where is located your `network.php` file.\n * @property {number} [delay=8000] The delay while you want to take measures.\n */\n\n/**\n * @class HttpModule\n * @extends EventDispatcher\n * @param {string} moduleName The name of the instanciated module.\n * @param {HttpModule~settingsObject} [settings={}] A set of custom settings.\n */\n\nvar HttpModule = (function (_EventDispatcher) {\n function HttpModule(moduleName) {\n var _this = this;\n\n var settings = arguments[1] === undefined ? {} : arguments[1];\n\n _classCallCheck(this, HttpModule);\n\n _get(Object.getPrototypeOf(HttpModule.prototype), 'constructor', this).call(this);\n\n this._extendDefaultSettings({\n endpoint: './network.php',\n delay: 8000\n });\n\n this.settings(settings);\n\n this._moduleName = moduleName;\n this._xhr = null;\n this._lastURLToken = null;\n\n this._requestingOverridden = false;\n this._requesting = false;\n\n // Each time a request starts or ends, set the requesting value unless it has been overridden with the\n // _setRequesting() method.\n this.on(['xhr-loadstart', 'xhr-upload-loadstart'], function () {\n if (!_this._requestingOverridden) {\n _this._requesting = true;\n }\n });\n\n this.on(['xhr-loadend', 'xhr-upload-loadend'], function () {\n if (!_this._requestingOverridden) {\n _this._requesting = false;\n }\n });\n }\n\n _inherits(HttpModule, _EventDispatcher);\n\n _createClass(HttpModule, [{\n key: 'settings',\n\n /**\n * Apply a new set of custom settings.\n * @public\n * @method HttpModule#settings\n * @param {HttpModule~settingsObject} settings A set of custom settings.\n * @returns {HttpModule}\n */\n /**\n * Return the current set of settings.\n * @public\n * @method HttpModule#settings^2\n * @returns {HttpModule~settingsObject}\n */\n value: function settings() {\n var _settings = arguments[0] === undefined ? null : arguments[0];\n\n if ((0, _utilsHelpers.isObject)(_settings)) {\n this._settings = (0, _utilsHelpers.assignStrict)(this._defaultSettings || {}, this._settings || {}, _settings);\n return this;\n } else {\n return this._settings || this._defaultSettings || {};\n }\n }\n }, {\n key: 'isRequesting',\n\n /**\n * Return if the module is currently making a request.\n * @public\n * @method HttpModule#isRequesting\n * @returns {boolean} `true` if the module is requesting, otherwise `false`.\n */\n value: function isRequesting() {\n return this._requesting;\n }\n }, {\n key: '_extendDefaultSettings',\n\n /**\n * Extend the set of default settings.\n * @protected\n * @method HttpModule#_extendDefaultSettings\n * @param {Object} settings The new properties to add to the default settings.\n * @returns {HttpModule}\n */\n value: function _extendDefaultSettings(settings) {\n this._defaultSettings = (0, _utilsHelpers.assign)(this._defaultSettings || {}, settings);\n return this;\n }\n }, {\n key: '_newRequest',\n\n /**\n * Create a new XHR request.\n * @protected\n * @method HttpModule#_newRequest\n * @param {string} httpMethod The HTTP method to use with the request, GET or POST.\n * @param {Object} queryParams The query parameters to use with the request.\n * @returns {HttpModule}\n */\n value: function _newRequest(httpMethod, queryParams) {\n var _this2 = this;\n\n // Check if a callback binded to the \"_newRequest\" event returns false, if it's the case, cancel the request\n // creation. If the requesting status has been overridden, there's no need to cancel the request since the user\n // should know what he's doing.\n if (!this.trigger('_newRequest') && !this._requestingOverridden) {\n console.warn('To ensure accurate measures, you can only make one request at a time.');\n return this;\n }\n\n var settings = this.settings(),\n xhr = new XMLHttpRequest(),\n validHttpMethods = ['GET', 'POST'];\n\n // Prepare the new request.\n if (! ~validHttpMethods.indexOf(httpMethod)) {\n console.warn('The HTTP method must be GET or POST.');\n return this;\n }\n\n queryParams = queryParams || {};\n\n // Generate an URL token to avoid any caching issues. This token will also allow to identify the request in the\n // Resource Timing entries.\n var tokenSuffix = new Date().getTime();\n this._lastURLToken = 'network-' + tokenSuffix;\n\n // Append the query parameters\n var url = settings.endpoint;\n url += ~url.indexOf('?') ? '&' : '?';\n url += 'module=' + this._moduleName;\n\n Object.keys(queryParams).forEach(function (param) {\n var value = encodeURIComponent(queryParams[param]);\n url += '&' + param + '=' + value;\n });\n\n url += '&' + this._lastURLToken;\n\n xhr.open(httpMethod, url);\n\n // Abort the previous request if it hasn't been sent\n if (this._xhr && this._xhr.readyState == XMLHttpRequest.OPENED) {\n this._xhr.abort();\n }\n\n // Replace the old request by the new one\n this._xhr = xhr;\n\n // Bind all the XHR events\n var events = ['loadstart', 'progress', 'abort', 'error', 'load', 'timeout', 'loadend', 'readystatechange'];\n\n events.forEach(function (eventType) {\n xhr.addEventListener(eventType, function () {\n for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n // A last progress event can be triggered once a request has timed out, ignore it.\n if (eventType == 'progress' && !_this2._requesting) return;\n\n _this2.trigger.apply(_this2, ['xhr-' + eventType, xhr].concat(args));\n });\n\n // The XMLHttpRequestUpload interface supports all the above event types except the \"readystatechange\" one\n if (eventType != 'readystatechange') {\n xhr.upload.addEventListener(eventType, function () {\n for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n\n _this2.trigger.apply(_this2, ['xhr-upload-' + eventType, xhr].concat(args));\n });\n }\n });\n\n // Define the timeout of the request. We don't use the native `timeout` property since it can distort the\n // measures.\n // See: https://github.com/nesk/network.js/issues/26\n var startTimeout = function startTimeout(xhr) {\n _this2.trigger('xhr-timeout');\n _this2.trigger('xhr-upload-timeout');\n setTimeout(function () {\n return xhr.abort();\n }, settings.delay);\n };\n\n this.on('xhr-upload-loadstart', startTimeout).on('xhr-readystatechange', (function (timeoutStarted) {\n return function (xhr) {\n if (!timeoutStarted && xhr.readyState == XMLHttpRequest.LOADING) {\n timeoutStarted = true;\n startTimeout(xhr);\n }\n };\n })(false));\n\n return this;\n }\n }, {\n key: '_sendRequest',\n\n /**\n * Send a newly created XHR request.\n * @protected\n * @method HttpModule#_sendRequest\n * @param {?*} [data=null] The data to send with the request.\n * @returns {HttpModule}\n */\n value: function _sendRequest() {\n var data = arguments[0] === undefined ? null : arguments[0];\n\n if (this._xhr && this._xhr.readyState == XMLHttpRequest.OPENED) {\n this._xhr.send(data);\n } else {\n console.warn('A request must have been created before sending any data.');\n }\n\n return this;\n }\n }, {\n key: '_abort',\n\n /**\n * Abort the current request.\n * @protected\n * @method HttpModule#_abort\n * @returns {HttpModule}\n */\n value: function _abort() {\n if (this._xhr) {\n this._xhr.abort();\n }\n\n return this;\n }\n }, {\n key: '_getTimingEntry',\n\n /**\n * Get the Resource Timing entry associated to the current request.\n * @protected\n * @method HttpModule#_getTimingEntry\n * @param {HttpModule~timingCallback} callback A callback used to send back the timing entry.\n * @returns {HttpModule}\n */\n value: function _getTimingEntry(callback) {\n // The Resource Timing entries aren't immediately available once the 'load' event is triggered by an\n // XMLHttpRequest, we must wait for another process tick to check for a refreshed list.\n setTimeout((function (lastURLToken) {\n return function () {\n // Filter the timing entries to return only the one concerned by the last request made\n var entries = performance.getEntriesByType('resource').filter(function (entry) {\n return ~entry.name.indexOf(lastURLToken);\n });\n\n /**\n * A callback used to send back the timing entry.\n * @private\n * @callback HttpModule~timingCallback\n * @param {PerformanceResourceTiming} entry The Resource Timing entry associated to the current request.\n */\n callback(entries.length ? entries[0] : null);\n };\n })(this._lastURLToken), 0);\n\n return this;\n }\n }, {\n key: '_setRequesting',\n\n /**\n * Override the requesting status of the module.\n * @protected\n * @method HttpModule#_setRequesting\n * @param {boolean} isRequesting The requesting status.\n * @returns {HttpModule}\n */\n value: function _setRequesting(isRequesting) {\n this._requestingOverridden = true;\n this._requesting = isRequesting;\n return this;\n }\n }]);\n\n return HttpModule;\n})(_EventDispatcher3['default']);\n\nexports['default'] = HttpModule;\nmodule.exports = exports['default'];\n\n},{\"../../utils/helpers\":7,\"../EventDispatcher\":1}],4:[function(require,module,exports){\n'use strict';\n\nObject.defineProperty(exports, '__esModule', {\n value: true\n});\n\nvar _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();\n\nvar _get = function get(_x5, _x6, _x7) { var _again = true; _function: while (_again) { var object = _x5, property = _x6, receiver = _x7; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x5 = parent; _x6 = property; _x7 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }\n\nvar _HttpModule2 = require('./HttpModule');\n\nvar _HttpModule3 = _interopRequireDefault(_HttpModule2);\n\nvar _Timing = require('../Timing');\n\nvar _Timing2 = _interopRequireDefault(_Timing);\n\nvar _utilsHelpers = require('../../utils/helpers');\n\n/**\n * @public\n * @typedef {Object} LatencyModule~settingsObject\n * @property {string} [endpoint=./network.php] Where is located your `network.php` file.\n * @property {number} [measures=5] How many measures should be returned.\n * @property {number} [attempts=3] How much attempts to get a valid value should be done for each measure.\n */\n\n/**\n * @class LatencyModule\n * @extends HttpModule\n * @param {LatencyModule~settingsObject} [settings={}] A set of custom settings.\n */\n\nvar LatencyModule = (function (_HttpModule) {\n function LatencyModule() {\n var _this = this;\n\n var settings = arguments[0] === undefined ? {} : arguments[0];\n\n _classCallCheck(this, LatencyModule);\n\n _get(Object.getPrototypeOf(LatencyModule.prototype), 'constructor', this).call(this, 'latency');\n\n this._extendDefaultSettings({\n measures: 5,\n attempts: 3\n }).settings(settings);\n\n // Define the object properties\n this._requestsLeft = 0;\n this._attemptsLeft = 0;\n\n this._latencies = [];\n this._requestID = 0;\n\n // Unique labels for each request, exclusively used to make measures.\n this._timingLabels = {\n start: null,\n end: null,\n measure: null\n };\n\n // Measure the latency with the Resource Timing API once the request is finished\n if (_Timing2['default'].supportsResourceTiming()) {\n this.on('xhr-load', function () {\n return _this._measure();\n });\n }\n\n // If the browser doesn't support the Resource Timing API, we fallback on a Datetime solution.\n else {\n // Set a mark when the request starts\n this.on('xhr-loadstart', function () {\n return _Timing2['default'].mark(_this._timingLabels.start);\n });\n\n // Then make a measure with the previous mark\n this.on('xhr-readystatechange', function (xhr) {\n return _this._measure(xhr);\n });\n }\n }\n\n _inherits(LatencyModule, _HttpModule);\n\n _createClass(LatencyModule, [{\n key: 'settings',\n\n /**\n * Apply a new set of custom settings.\n * @public\n * @method LatencyModule#settings\n * @param {LatencyModule~settingsObject} settings A set of custom settings.\n * @returns {LatencyModule}\n */\n /**\n * Return the current set of settings.\n * @public\n * @method LatencyModule#settings^2\n * @returns {LatencyModule~settingsObject}\n */\n value: function settings() {\n var _settings = arguments[0] === undefined ? null : arguments[0];\n\n if ((0, _utilsHelpers.isObject)(_settings)) {\n return _get(Object.getPrototypeOf(LatencyModule.prototype), 'settings', this).call(this, (0, _utilsHelpers.assignStrict)(_settings, {\n delay: 0 // We dont want any timeout during a latency calculation\n }));\n } else {\n return (0, _utilsHelpers.except)(_get(Object.getPrototypeOf(LatencyModule.prototype), 'settings', this).call(this), ['delay']);\n }\n }\n }, {\n key: 'start',\n\n /**\n * Start requesting the server to make measures.\n * @public\n * @method LatencyModule#start\n * @returns {LatencyModule}\n */\n value: function start() {\n // Set the number of requests required to establish the network latency. If the browser doesn't support the\n // Resource Timing API, add a request that will be ignored to avoid a longer request due to a possible\n // DNS/whatever fetch.\n\n var _settings2 = this.settings();\n\n var measures = _settings2.measures;\n var attempts = _settings2.attempts;\n\n this._requestsLeft = measures;\n this._attemptsLeft = attempts * measures;\n\n if (!_Timing2['default'].supportsResourceTiming()) {\n this._requestsLeft++;\n this._attemptsLeft++;\n }\n\n // Override the requesting value since a complete latency request consists off multiple ones\n this._setRequesting(true);\n\n this._latencies = [];\n this._nextRequest();\n\n return this;\n }\n }, {\n key: '_nextRequest',\n\n /**\n * Initiate the next request used for latency measures.\n * @private\n * @method LatencyModule#_nextRequest\n * @param {boolean} [retry=false] Defines if the next request is a retry due to a failing request or not.\n * @returns {LatencyModule}\n */\n value: function _nextRequest() {\n var _this2 = this;\n\n var retry = arguments[0] === undefined ? false : arguments[0];\n\n var reqID = this._requestID++;\n var requestsLeft = retry ? this._requestsLeft : this._requestsLeft--;\n\n if (this._attemptsLeft-- && (requestsLeft || retry)) {\n // Create unique timing labels for the new request\n var labels = this._timingLabels;\n labels.start = 'latency-' + reqID + '-start';\n labels.end = 'latency-' + reqID + '-end';\n labels.measure = 'latency-' + reqID + '-measure';\n\n // Create the new request and send it\n this._newRequest('GET')._sendRequest();\n } else {\n // All the requests are finished, set the requesting status to false.\n this._setRequesting(false);\n\n // If all the requests have been executed, calculate the average latency. Since the _getTimingEntry() method\n // is asynchronous, wait for the next process tick to execute the _end() method, to be sure that all the\n // latencies have been retrieved.\n setTimeout(function () {\n return _this2._end();\n }, 0);\n }\n\n return this;\n }\n }, {\n key: '_measure',\n\n /**\n * Make latency measures for the last request.\n * @private\n * @method LatencyModule#_measure\n * @param {?XMLHttpRequest} [xhr=null] The concerned XMLHttpRequest if the browser doesn't support the Resource Timing API.\n * @returns {LatencyModule}\n */\n value: function _measure() {\n var _this3 = this;\n\n var xhr = arguments[0] === undefined ? null : arguments[0];\n\n // With Resource Timing API\n if (!xhr) {\n this._getTimingEntry(function (entry) {\n // The latency calculation differs between an HTTP and an HTTPS connection\n // See: http://www.w3.org/TR/resource-timing/#processing-model\n var latency = !entry.secureConnectionStart ? entry.connectEnd - entry.connectStart : entry.secureConnectionStart - entry.connectStart;\n\n if (latency) _this3._latencies.push(latency);\n _this3._nextRequest(!latency);\n });\n }\n\n // Without Resource Timing API\n else if (this._requestsLeft < this.settings().measures) {\n\n // Measure and save the latency if the headers have been received\n if (xhr.readyState == XMLHttpRequest.HEADERS_RECEIVED) {\n var labels = this._timingLabels;\n\n _Timing2['default'].mark(labels.end);\n var latency = _Timing2['default'].measure(labels.measure, labels.start, labels.end);\n\n if (latency) this._latencies.push(latency);\n\n // Abort the current request before we run a new one\n this._abort();\n this._nextRequest(!latency);\n }\n }\n\n // Ignore the first request when using the XHR states. See the comments in the start() method for explanations.\n else {\n this._nextRequest();\n }\n\n return this;\n }\n }, {\n key: '_end',\n\n /**\n * End the measures.\n * @private\n * @method LatencyModule#_end\n * @returns {LatencyModule}\n */\n value: function _end() {\n var latencies = this._latencies;\n\n // Get the average latency\n var avgLatency = latencies.reduce(function (a, b) {\n return a + b;\n }, 0) / (latencies.length || 1);\n avgLatency = avgLatency || null;\n\n // If there is not enough measures, display a warning.\n if (latencies.length < this.settings().measures) {\n var _settings3 = this.settings();\n\n var measures = _settings3.measures;\n var attempts = _settings3.attempts;\n\n console.warn(['An insufficient number of measures have been processed, this could be due to your web server using', 'persistant connections or to your client settings (measures: ' + measures + ', attempts: ' + attempts + ')'].join(' '));\n }\n\n // Trigger the \"end\" event with the average latency and the latency list as parameters\n this.trigger('end', avgLatency, latencies);\n\n return this;\n }\n }]);\n\n return LatencyModule;\n})(_HttpModule3['default']);\n\nexports['default'] = LatencyModule;\nmodule.exports = exports['default'];\n\n},{\"../../utils/helpers\":7,\"../Timing\":6,\"./HttpModule\":3}],5:[function(require,module,exports){\n'use strict';\n\nObject.defineProperty(exports, '__esModule', {\n value: true\n});\n\nvar _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }\n\nvar _EventDispatcher = require('./EventDispatcher');\n\nvar _EventDispatcher2 = _interopRequireDefault(_EventDispatcher);\n\nvar _HttpHttpModule = require('./Http/HttpModule');\n\nvar _HttpHttpModule2 = _interopRequireDefault(_HttpHttpModule);\n\nvar _HttpLatencyModule = require('./Http/LatencyModule');\n\nvar _HttpLatencyModule2 = _interopRequireDefault(_HttpLatencyModule);\n\nvar _HttpBandwidthModule = require('./Http/BandwidthModule');\n\nvar _HttpBandwidthModule2 = _interopRequireDefault(_HttpBandwidthModule);\n\nvar _Timing = require('./Timing');\n\nvar _Timing2 = _interopRequireDefault(_Timing);\n\nvar _utilsHelpers = require('../utils/helpers');\n\n/**\n * @public\n * @typedef {Object} Network~settingsObject\n * @property {LatencyModule~settingsObject} latency\n * @property {BandwidthModule~settingsObject} upload\n * @property {BandwidthModule~settingsObject} download\n * @example\n * {\n * // Top-level properties are applied to all the modules\n * endpoint: './my-new-endpoint/',\n *\n * // Top-level properties will be overridden by the ones specified in each module\n * latency: {\n * endpoint: './my-new-latency-endpoint/'\n * }\n * }\n */\n\n/**\n * @class Network\n * @param {Network~settingsObject} [settings={}] A set of custom settings.\n * @member {LatencyModule} latency The latency module.\n * @member {BandwidthModule} upload The upload module.\n * @member {BandwidthModule} download The download module.\n */\n\nvar Network = (function () {\n function Network() {\n var settings = arguments[0] === undefined ? {} : arguments[0];\n\n _classCallCheck(this, Network);\n\n this._modules = {};\n this._modulesInitialized = false;\n this._pendingSettings = {};\n\n this._registerModule('latency', function (settings) {\n return new _HttpLatencyModule2['default'](settings);\n })._registerModule('upload', function (settings) {\n return new _HttpBandwidthModule2['default']('upload', settings);\n })._registerModule('download', function (settings) {\n return new _HttpBandwidthModule2['default']('download', settings);\n });\n\n this._initModules(this.settings(settings));\n }\n\n _createClass(Network, [{\n key: 'settings',\n\n /**\n * Apply a new set of custom settings.\n * @public\n * @method Network#settings\n * @param {Network~settingsObject} settings A set of custom settings.\n * @returns {Network}\n */\n /**\n * Return the current set of settings.\n * @public\n * @method Network#settings^2\n * @returns {Network~settingsObject}\n */\n value: function settings() {\n var _this = this;\n\n var _settings = arguments[0] === undefined ? null : arguments[0];\n\n var moduleNames = Object.keys(this._modules);\n\n if ((0, _utilsHelpers.isObject)(_settings)) {\n var _ret = (function () {\n // Extract the global settings\n var globalSettings = (0, _utilsHelpers.except)(_settings, moduleNames);\n\n // Extract the local settings\n var localSettings = (0, _utilsHelpers.except)(_settings, Object.keys(globalSettings));\n\n // Create new settings with the global ones nested in the local ones\n _settings = moduleNames.reduce(function (settings, moduleName) {\n return (0, _utilsHelpers.assign)(settings, _defineProperty({}, moduleName, globalSettings));\n }, {});\n\n // Apply the local settings to the new settings\n _settings = (0, _utilsHelpers.assign)(_settings, localSettings);\n\n // Apply the settings to the modules\n if (_this._modulesInitialized) {\n Object.keys(_this._modules).forEach(function (name) {\n _this._modules[name].settings(_settings[name]);\n });\n }\n\n // If the modules aren't instanciated, store the settings.\n else {\n _this._pendingSettings = _settings;\n }\n\n return {\n v: _this\n };\n })();\n\n if (typeof _ret === 'object') return _ret.v;\n } else {\n return moduleNames.reduce(function (settings, moduleName) {\n return (0, _utilsHelpers.assign)(settings, _defineProperty({}, moduleName, _this._modules[moduleName].settings()));\n }, {});\n }\n }\n }, {\n key: 'isRequesting',\n\n /**\n * Return if a module is currently making a request.\n * @public\n * @method Network#isRequesting\n * @returns {boolean} `true` if a module is requesting, otherwise `false`.\n */\n value: function isRequesting() {\n var requesting = false;\n\n for (var _name in this._modules) {\n if (this._modules.hasOwnProperty(_name)) {\n requesting = requesting || this._modules[_name].isRequesting();\n }\n }\n\n return requesting;\n }\n }, {\n key: '_registerModule',\n\n /**\n * Register a new module for the current `Network` instance.\n * @private\n * @method Network#registerModule\n * @param {string} name The name of the module. Will be used to create the property `Network.`.\n * @param {Network~moduleCallback} moduleCallback A callback used to initialize a module with a set of settings.\n * @returns {Network}\n */\n value: function _registerModule(name, moduleCallback) {\n /**\n * A callback used to initialize a module with a set of settings.\n * @private\n * @callback Network~moduleCallback\n * @param {Object} settings A set of custom settings.\n * @returns {HttpModule} An instanciated subclass of `HttpModule`.\n */\n this._modules[name] = moduleCallback;\n return this;\n }\n }, {\n key: '_initModules',\n\n /**\n * Initialize all the registered modules with the settings passed to the constructor.\n * @private\n * @method Network#_initModules\n * @returns {Network}\n */\n value: function _initModules() {\n var _this2 = this;\n\n if (!this._modulesInitialized) {\n // Initialize the modules with their respective settings\n Object.keys(this._modules).forEach(function (name) {\n _this2._modules[name] = _this2._modules[name](_this2._pendingSettings[name]).on('_newRequest', function () {\n return !_this2.isRequesting();\n });\n\n _this2[name] = _this2._modules[name];\n });\n\n this._modulesInitialized = true;\n }\n\n return this;\n }\n }], [{\n key: '_exposeInternalClasses',\n\n /**\n * Expose all the internal classes to the global scope. Only for testing purposes!\n * @private\n * @method Network._exposeInternalClasses\n * @returns {Network}\n */\n value: function _exposeInternalClasses() {\n var global = (0, _utilsHelpers.getGlobalObject)(),\n classes = { EventDispatcher: _EventDispatcher2['default'], HttpModule: _HttpHttpModule2['default'], LatencyModule: _HttpLatencyModule2['default'], BandwidthModule: _HttpBandwidthModule2['default'], Timing: _Timing2['default'] };\n\n Object.keys(classes).forEach(function (name) {\n global[name] = classes[name];\n });\n\n return this;\n }\n }]);\n\n return Network;\n})();\n\nexports['default'] = Network;\nmodule.exports = exports['default'];\n\n},{\"../utils/helpers\":7,\"./EventDispatcher\":1,\"./Http/BandwidthModule\":2,\"./Http/HttpModule\":3,\"./Http/LatencyModule\":4,\"./Timing\":6}],6:[function(require,module,exports){\n'use strict';\n\nObject.defineProperty(exports, '__esModule', {\n value: true\n});\n\nvar _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }\n\nvar _utilsHelpers = require('../utils/helpers');\n\n/**\n * @private\n * @class Timing\n */\n\nvar Timing = (function () {\n function Timing() {\n _classCallCheck(this, Timing);\n\n var global = (0, _utilsHelpers.getGlobalObject)();\n\n /**\n * Defines if the current browser supports some specific Timing APIs.\n * @private\n * @member {Object} _support\n * @property {boolean} performance `true` if the Performance API is available.\n * @property {boolean} userTiming `true` if the User Timing API is available.\n * @property {boolean} resourceTiming `true` if the Resource Timing API is available.\n */\n this._support = {\n performance: !!global.performance,\n userTiming: global.performance && performance.mark,\n resourceTiming: global.performance && typeof performance.getEntriesByType == 'function' && performance.timing\n };\n\n /**\n * Contains all the marks created by the `mark` method.\n * @private\n * @member {Object} _marks\n */\n this._marks = {};\n\n /**\n * Contains all the measures created by the `measure` method.\n * @private\n * @member {Object} _measures\n */\n this._measures = {};\n }\n\n _createClass(Timing, [{\n key: 'mark',\n\n /**\n * Create a new timing mark.\n * @public\n * @method Timing#mark\n * @param {string} label A label associated to the mark.\n * @returns {Timing}\n */\n value: function mark(label) {\n var support = this._support,\n marks = this._marks;\n\n if (support.userTiming) {\n performance.mark(label);\n }\n\n if (support.performance) {\n marks[label] = performance.now();\n } else {\n marks[label] = new Date().getTime();\n }\n\n return this;\n }\n }, {\n key: 'measure',\n\n /**\n * Measure the delay between two marks.\n * @public\n * @method Timing#measure\n * @param {string} measureLabel A label associated to the measure.\n * @param {string} markLabelA The label of the first mark.\n * @param {string} markLabelB The label of the second mark.\n * @returns {number} The measured value.\n */\n value: function measure(measureLabel, markLabelA, markLabelB) {\n var support = this._support,\n marks = this._marks,\n measures = this._measures;\n\n if (typeof measures[measureLabel] == 'undefined') {\n var measureWithoutUserTiming = marks[markLabelB] - marks[markLabelA];\n\n if (support.userTiming) {\n performance.measure(measureLabel, markLabelA, markLabelB);\n var entriesByName = performance.getEntriesByName(measureLabel);\n\n // The performance API could return no corresponding entries in Firefox so we must use a fallback.\n // See: https://github.com/nesk/network.js/issues/32#issuecomment-118434305\n measures[measureLabel] = entriesByName.length ? entriesByName[0].duration : measureWithoutUserTiming;\n } else {\n measures[measureLabel] = measureWithoutUserTiming;\n }\n }\n\n return measures[measureLabel];\n }\n }, {\n key: 'supportsResourceTiming',\n\n /**\n * Determine if the current browser supports the Resource Timing API.\n * @public\n * @method Timing#supportsResourceTiming\n * @returns {boolean} `true` if the Resource Timing API is supported, otherwise `false`.\n */\n value: function supportsResourceTiming() {\n return this._support.resourceTiming;\n }\n }]);\n\n return Timing;\n})();\n\nexports['default'] = new Timing();\nmodule.exports = exports['default'];\n\n},{\"../utils/helpers\":7}],7:[function(require,module,exports){\n(function (global){\n/**\n * Return the global object.\n * @private\n * @function getGlobalObject\n * @return {Object}\n * @see https://gist.github.com/rauschma/1bff02da66472f555c75\n */\n'use strict';\n\nObject.defineProperty(exports, '__esModule', {\n value: true\n});\n\nvar _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();\n\nexports.getGlobalObject = getGlobalObject;\nexports.isObject = isObject;\nexports.copy = copy;\nexports.assign = assign;\nexports.assignStrict = assignStrict;\nexports.except = except;\nexports.defer = defer;\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }\n\nfunction getGlobalObject() {\n // Workers don’t have `window`, only `self`.\n if (typeof self !== 'undefined') {\n return self;\n }\n\n if (typeof global !== 'undefined') {\n return global;\n }\n\n // Not all environments allow `eval` and `Function`, use only as a last resort.\n return new Function('return this')();\n}\n\n/**\n * Determine if the provided value is an object.\n * @private\n * @function isObject\n * @param {*} obj The value to check.\n * @returns {boolean} `true` if the value is an object, otherwise `false`.\n */\n\nfunction isObject(obj) {\n return obj != undefined && obj != null && typeof obj.valueOf() == 'object';\n}\n\n/**\n * Make a deep copy of any value.\n * @private\n * @function copy\n * @param {*} value The value to copy.\n * @returns {*} The copied value.\n */\n\nfunction copy(value) {\n return JSON.parse(JSON.stringify(value));\n}\n\n/**\n * Copy the properties in the source objects over to the destination object.\n * @private\n * @function _assign\n * @param {boolean} strict Given `true`, new properties will not be copied.\n * @param {Object} [target={}] The destination object.\n * @param {...Object} sources The source objects.\n * @returns {Object} The destination object once the properties are copied.\n */\nfunction _assign(strict) {\n var target = arguments[1] === undefined ? {} : arguments[1];\n\n target = copy(target);\n\n for (var _len = arguments.length, sources = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {\n sources[_key - 2] = arguments[_key];\n }\n\n sources.forEach(function (source) {\n Object.keys(source).forEach(function (key) {\n if (!strict || target.hasOwnProperty(key)) {\n var value = source[key];\n target[key] = isObject(value) ? _assign(strict, target[key], value) : value;\n }\n });\n });\n\n return target;\n}\n\n/**\n * Copy all the properties in the source objects over to the destination object.\n * @private\n * @function assign\n * @param {Object} [target={}] The destination object.\n * @param {...Object} sources The source objects.\n * @returns {Object} The destination object once the properties are copied.\n */\n\nfunction assign() {\n var target = arguments[0] === undefined ? {} : arguments[0];\n\n for (var _len2 = arguments.length, sources = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n sources[_key2 - 1] = arguments[_key2];\n }\n\n return _assign.apply(undefined, [false, target].concat(sources));\n}\n\n/**\n * Copy the properties (but no new ones) in the source objects over to the destination object.\n * @private\n * @function assignStrict\n * @param {Object} [target={}] The destination object.\n * @param {...Object} sources The source objects.\n * @returns {Object} The destination object once the properties are copied.\n */\n\nfunction assignStrict() {\n var target = arguments[0] === undefined ? {} : arguments[0];\n\n for (var _len3 = arguments.length, sources = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n sources[_key3 - 1] = arguments[_key3];\n }\n\n return _assign.apply(undefined, [true, target].concat(sources));\n}\n\n/**\n * Get a copy of an object without some of its properties.\n * @private\n * @function except\n * @param {Object} obj The original object.\n * @param {string[]} properties The properties to exclude from the copied object.\n * @returns {Object} The copied object without the specified properties.\n */\n\nfunction except(obj, properties) {\n var objCopy = copy(obj);\n\n properties.forEach(function (index) {\n return delete objCopy[index];\n });\n\n return objCopy;\n}\n\n/**\n * Defer the execution of a function.\n * @private\n * @function defer\n * @param {Function} func The function to defer.\n * @returns {Defer} The Defer object used to execute the function when needed.\n */\n\nfunction defer() {\n var func = arguments[0] === undefined ? function () {} : arguments[0];\n\n /**\n * @private\n * @class Defer\n */\n return new ((function () {\n var _class = function _class() {\n _classCallCheck(this, _class);\n\n this.func = func;\n };\n\n _createClass(_class, [{\n key: 'run',\n\n /**\n * Execute the deferred function.\n * @public\n * @method Defer#run\n */\n value: function run() {\n if (this.func) this.func();\n delete this.func;\n }\n }]);\n\n return _class;\n })())();\n}\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n\n},{}]},{},[5])(5)\n});\n//# sourceMappingURL=network.js.map\n","/**\n * @class EventDispatcher\n */\nexport default class EventDispatcher {\n\n /**\n * A callback used as an event handler.\n * @public\n * @callback EventDispatcher~eventHandler\n * @param {...*} args The extra parameters provided to the `trigger` method.\n * @returns {?boolean} If `false` is explicitly returned, the `trigger` method will return `false`.\n */\n\n constructor()\n {\n /**\n * Contains all the event callbacks, organized by events.\n * @private\n * @type {Object}\n */\n this._eventCallbacks = {};\n }\n\n /**\n * Attach a callback to one or more events.\n * @public\n * @method EventDispatcher#on\n * @param {string|string[]} events One or multiple event names.\n * @param {EventDispatcher~eventHandler} callback An event handler.\n * @returns {EventDispatcher}\n */\n on(events, callback)\n {\n events = Array.isArray(events) ? events : [events];\n\n events.forEach(event => {\n var eventCallbacks = this._eventCallbacks[event] = this._eventCallbacks[event] || [];\n\n // If the callback isn't already registered, store it.\n if (!~eventCallbacks.indexOf(callback)) {\n eventCallbacks.push(callback);\n }\n });\n\n return this;\n }\n\n /**\n * Detach a callback from one or more events.\n * @public\n * @method EventDispatcher#off\n * @param {string|string[]} events One or multiple event names.\n * @param {EventDispatcher~eventHandler} callback An event handler.\n * @returns {EventDispatcher}\n */\n off(events, callback = null)\n {\n events = Array.isArray(events) ? events : [events];\n\n events.forEach(event => {\n var eventCallbacks = this._eventCallbacks[event];\n\n // If there is no specified callback, simply delete all the callbacks binded to the provided event.\n if (!callback && eventCallbacks) {\n delete this._eventCallbacks[event];\n } else {\n var callbackIndex = eventCallbacks ? eventCallbacks.indexOf(callback) : -1;\n\n // If the callback is registered, remove it from the array.\n if (callbackIndex != -1) {\n eventCallbacks.splice(callbackIndex, 1);\n }\n }\n });\n\n return this;\n }\n\n /**\n * Trigger an event.\n * @public\n * @method EventDispatcher#trigger\n * @param {string} event An event name.\n * @param {...*} extraParameters Some extra parameters to pass to the event handlers.\n * @returns {boolean} Returns `false` if one of the event handlers explicitly returned `false`.\n */\n trigger(event, ...extraParameters)\n {\n var eventCallbacks = this._eventCallbacks[event] || [];\n\n // A callback can return a boolean value which will be logically compared to the other callbacks values before\n // being returned by the trigger() method. This allows a callback to send a \"signal\" to the caller, like\n // cancelling an action.\n var returnValue = true;\n\n eventCallbacks.forEach(eventCallback => {\n // A callback must explicitly return false if it wants the trigger() method to return false, undefined will\n // not work. This avoids crappy callbacks to mess up with the triggering system.\n var value = eventCallback(...extraParameters);\n value = value !== false ? true : false;\n\n returnValue = returnValue && value; // Compare the result of the callback to the actual return value\n });\n\n return returnValue;\n }\n\n}\n","import HttpModule from './HttpModule';\nimport Timing from '../Timing';\nimport {defer} from '../../utils/helpers';\n\n/**\n * @public\n * @typedef {Object} BandwidthModule~settingsObject\n * @extends HttpModule~settingsObject\n * @property {Object} data\n * @property {number} data.size The amount of data to initially use.\n * @property {number} [data.multiplier=2] If the measure period can't reach the delay defined in the settings, the data amount is multiplied by the following value.\n */\n\n/**\n * Apply a new set of custom settings.\n * @public\n * @method BandwidthModule#settings\n * @param {BandwidthModule~settingsObject} settings A set of custom settings.\n * @returns {BandwidthModule}\n */\n/**\n * Return the current set of settings.\n * @public\n * @method BandwidthModule#settings^2\n * @returns {BandwidthModule~settingsObject}\n */\n\n/**\n * @class BandwidthModule\n * @extends HttpModule\n * @param {string} loadingType The loading type, `upload` or `download`.\n * @param {BandwidthModule~settingsObject} [settings={}] A set of custom settings.\n */\nexport default class BandwidthModule extends HttpModule {\n\n constructor(loadingType, settings = {})\n {\n loadingType = (~['upload', 'download'].indexOf(loadingType)) ? loadingType : 'download';\n\n super(loadingType);\n\n this._extendDefaultSettings({\n data: {\n // 2 MB for upload, 10 MB for download\n size: loadingType == 'upload' ? (2 * 1024 * 1024) : (10 * 1024 * 1024),\n multiplier: 2\n }\n }).settings(settings);\n\n // Define the object properties\n this._loadingType = loadingType;\n\n this._intendedEnd = false;\n this._isRestarting = false;\n\n this._lastLoadedValue = null;\n this._speedRecords = [];\n this._avgSpeed = null;\n\n this._requestID = 0;\n this._progressID = 0;\n\n this._started = false;\n this._firstProgress = true;\n this._deferredProgress;\n\n // Unique labels for each request, exclusively used to make measures.\n this._timingLabels = {\n start: null,\n progress: null,\n end: null,\n measure: null\n };\n\n // Bind to XHR events\n this.on('xhr-upload-loadstart', () => Timing.mark(this._timingLabels.start));\n this.on('xhr-readystatechange', xhr => {\n if (!this._started && xhr.readyState == XMLHttpRequest.LOADING) {\n Timing.mark(this._timingLabels.start);\n this._started = true;\n }\n });\n\n var eventsPrefix = (loadingType == 'upload') ? 'xhr-upload' : 'xhr';\n\n this.on(`${eventsPrefix}-progress`, (xhr, event) => this._progress(event));\n this.on(`${eventsPrefix}-timeout`, () => this._timeout());\n this.on(`${eventsPrefix}-loadend`, () => this._end());\n }\n\n /**\n * Start requesting the server to make measures.\n * @public\n * @method BandwidthModule#start\n * @returns {BandwidthModule}\n */\n start()\n {\n var loadingType = this._loadingType,\n dataSettings = this.settings().data,\n reqID = this._requestID++;\n\n this._intendedEnd = false;\n this._lastLoadedValue = null;\n this._speedRecords = [];\n this._started = false;\n this._firstProgress = true;\n this._deferredProgress = defer();\n\n // Trigger the start event\n if (!this._isRestarting) {\n this.trigger('start', dataSettings.size);\n }\n\n // Create unique timing labels for the new request\n var labels = this._timingLabels;\n labels.start = `${loadingType}-${reqID}-start`;\n labels.progress = `${loadingType}-${reqID}-progress`;\n labels.end = `${loadingType}-${reqID}-end`;\n labels.measure = `${loadingType}-${reqID}-measure`;\n\n // Generate some random data to upload to the server. Here we're using a Blob instead of an ArrayBuffer because\n // of a bug in Chrome (tested in v33.0.1750.146), causing a freeze of the page while trying to directly upload\n // an ArrayBuffer (through an ArrayBufferView). The freeze lasts nearly 4.5s for 10MB of data. Using a Blob\n // seems to solve the problem.\n var blob = (loadingType == 'upload') ? new Blob([new ArrayBuffer(dataSettings.size)]) : null;\n\n var type = (loadingType == 'download') ? 'GET' : 'POST';\n\n // Initiate and send a new request\n this._newRequest(type, {\n size: dataSettings.size\n })._sendRequest(blob);\n\n return this;\n }\n\n /**\n * Abort the measures.\n * @public\n * @method BandwidthModule#abort\n * @returns {BandwidthModule}\n */\n abort()\n {\n this._intendedEnd = true;\n return this._abort();\n }\n\n /**\n * Make bandwidth measures for the current request.\n * @private\n * @method BandwidthModule#_progress\n * @param {ProgressEvent} event The event associated with the progress event of the current request.\n * @returns {BandwidthModule}\n */\n _progress(event)\n {\n // Ignore the first progress event, it generally contributes to get incoherent values.\n if (this._firstProgress) return this._firstProgress = false;\n\n // Execute the previous progress trigger\n this._deferredProgress.run();\n\n var labels = this._timingLabels,\n progressID = this._progressID++,\n markLabel = `${labels.progress}-${progressID}`,\n loaded = event.loaded;\n\n Timing.mark(markLabel);\n\n // Measure the average speed (B/s) since the request started\n var avgMeasure = Timing.measure(\n `${labels.measure}-avg-${progressID}`,\n labels.start,\n markLabel\n ),\n avgSpeed = loaded / avgMeasure * 1000;\n\n var instantSpeed;\n\n if (!this._lastLoadedValue) { // We are executing the first progress event of the current request\n instantSpeed = avgSpeed; // The instant speed of the first progress event is equal to the average one\n } else {\n // Measure the instant speed (B/s), which defines the speed between two progress events.\n var instantMeasure = Timing.measure(\n `${labels.measure}-instant-${progressID}`,\n // Set the mark of the previous progress event as the starting point\n `${labels.progress}-${progressID - 1}`,\n markLabel\n );\n instantSpeed = (loaded - this._lastLoadedValue) / instantMeasure * 1000;\n }\n\n // Save the `loaded` property of the event for the next progress event\n this._lastLoadedValue = loaded;\n\n // Defer measures saving and event triggering, this allows to cancel the last progress event, which can generate\n // incoherent values.\n this._deferredProgress = defer(() => {\n this._avgSpeed = avgSpeed;\n this._speedRecords.push(instantSpeed);\n\n this.trigger('progress', avgSpeed, instantSpeed);\n });\n\n return this;\n }\n\n /**\n * Mark the current request as entirely finished (this means it ended after a time out).\n * @private\n * @method BandwidthModule#_timeout\n * @returns {BandwidthModule}\n */\n _timeout()\n {\n this._intendedEnd = true;\n return this;\n }\n\n /**\n * End the measures.\n * @private\n * @method BandwidthModule#_end\n * @returns {BandwidthModule}\n */\n _end()\n {\n // A timeout or an abort occured, bypass the further requests and trigger the \"end\" event.\n if (this._intendedEnd) {\n this._isRestarting = false;\n this.trigger('end', this._avgSpeed, this._speedRecords);\n }\n\n // The request ended to early, restart it with an increased data size.\n else {\n var loadingType = this._loadingType,\n dataSettings = this.settings().data;\n\n dataSettings.size *= dataSettings.multiplier;\n\n this.trigger('restart', dataSettings.size);\n\n this._isRestarting = true;\n this.start();\n }\n\n return this;\n }\n\n\n}\n","import EventDispatcher from '../EventDispatcher';\nimport {isObject, assign, assignStrict} from '../../utils/helpers';\n\n/**\n * @public\n * @typedef {Object} HttpModule~settingsObject\n * @property {string} [endpoint=./network.php] Where is located your `network.php` file.\n * @property {number} [delay=8000] The delay while you want to take measures.\n */\n\n/**\n * @class HttpModule\n * @extends EventDispatcher\n * @param {string} moduleName The name of the instanciated module.\n * @param {HttpModule~settingsObject} [settings={}] A set of custom settings.\n */\nexport default class HttpModule extends EventDispatcher {\n\n constructor(moduleName, settings = {})\n {\n super();\n\n this._extendDefaultSettings({\n endpoint: './network.php',\n delay: 8000\n });\n\n this.settings(settings);\n\n this._moduleName = moduleName;\n this._xhr = null;\n this._lastURLToken = null;\n\n this._requestingOverridden = false;\n this._requesting = false;\n\n // Each time a request starts or ends, set the requesting value unless it has been overridden with the\n // _setRequesting() method.\n this.on(['xhr-loadstart', 'xhr-upload-loadstart'], () => {\n if (!this._requestingOverridden) {\n this._requesting = true;\n }\n });\n\n this.on(['xhr-loadend', 'xhr-upload-loadend'], () => {\n if (!this._requestingOverridden) {\n this._requesting = false;\n }\n });\n }\n\n /**\n * Apply a new set of custom settings.\n * @public\n * @method HttpModule#settings\n * @param {HttpModule~settingsObject} settings A set of custom settings.\n * @returns {HttpModule}\n */\n /**\n * Return the current set of settings.\n * @public\n * @method HttpModule#settings^2\n * @returns {HttpModule~settingsObject}\n */\n settings(settings = null)\n {\n if (isObject(settings)) {\n this._settings = assignStrict(this._defaultSettings || {}, this._settings || {}, settings);\n return this;\n } else {\n return this._settings || this._defaultSettings || {};\n }\n }\n\n /**\n * Return if the module is currently making a request.\n * @public\n * @method HttpModule#isRequesting\n * @returns {boolean} `true` if the module is requesting, otherwise `false`.\n */\n isRequesting()\n {\n return this._requesting;\n }\n\n /**\n * Extend the set of default settings.\n * @protected\n * @method HttpModule#_extendDefaultSettings\n * @param {Object} settings The new properties to add to the default settings.\n * @returns {HttpModule}\n */\n _extendDefaultSettings(settings)\n {\n this._defaultSettings = assign(this._defaultSettings || {}, settings);\n return this;\n }\n\n /**\n * Create a new XHR request.\n * @protected\n * @method HttpModule#_newRequest\n * @param {string} httpMethod The HTTP method to use with the request, GET or POST.\n * @param {Object} queryParams The query parameters to use with the request.\n * @returns {HttpModule}\n */\n _newRequest(httpMethod, queryParams)\n {\n // Check if a callback binded to the \"_newRequest\" event returns false, if it's the case, cancel the request\n // creation. If the requesting status has been overridden, there's no need to cancel the request since the user\n // should know what he's doing.\n if (!this.trigger('_newRequest') && !this._requestingOverridden) {\n console.warn('To ensure accurate measures, you can only make one request at a time.');\n return this;\n }\n\n let settings = this.settings(),\n xhr = new XMLHttpRequest(),\n validHttpMethods = ['GET', 'POST'];\n\n // Prepare the new request.\n if (!~validHttpMethods.indexOf(httpMethod)) {\n console.warn('The HTTP method must be GET or POST.');\n return this;\n }\n\n queryParams = queryParams || {};\n\n // Generate an URL token to avoid any caching issues. This token will also allow to identify the request in the\n // Resource Timing entries.\n let tokenSuffix = (new Date).getTime();\n this._lastURLToken = `network-${tokenSuffix}`;\n\n // Append the query parameters\n let url = settings.endpoint;\n url += ~url.indexOf('?') ? '&' : '?';\n url += `module=${this._moduleName}`;\n\n Object.keys(queryParams).forEach(param => {\n let value = encodeURIComponent(queryParams[param]);\n url += `&${param}=${value}`;\n });\n\n url += `&${this._lastURLToken}`;\n\n xhr.open(httpMethod, url);\n\n // Abort the previous request if it hasn't been sent\n if (this._xhr && this._xhr.readyState == XMLHttpRequest.OPENED) {\n this._xhr.abort();\n }\n\n // Replace the old request by the new one\n this._xhr = xhr;\n\n // Bind all the XHR events\n const events = [\n 'loadstart', 'progress', 'abort', 'error', 'load', 'timeout', 'loadend', 'readystatechange'\n ];\n\n events.forEach(eventType => {\n xhr.addEventListener(eventType, (...args) => {\n // A last progress event can be triggered once a request has timed out, ignore it.\n if (eventType == 'progress' && !this._requesting) return;\n\n this.trigger(`xhr-${eventType}`, xhr, ...args);\n });\n\n // The XMLHttpRequestUpload interface supports all the above event types except the \"readystatechange\" one\n if (eventType != 'readystatechange') {\n xhr.upload.addEventListener(eventType, (...args) => {\n this.trigger(`xhr-upload-${eventType}`, xhr, ...args);\n });\n }\n });\n\n // Define the timeout of the request. We don't use the native `timeout` property since it can distort the\n // measures.\n // See: https://github.com/nesk/network.js/issues/26\n const startTimeout = xhr => {\n this.trigger('xhr-timeout');\n this.trigger('xhr-upload-timeout');\n setTimeout(() => xhr.abort(), settings.delay);\n };\n\n this.on('xhr-upload-loadstart', startTimeout).on('xhr-readystatechange', (timeoutStarted => {\n return xhr => {\n if (!timeoutStarted && xhr.readyState == XMLHttpRequest.LOADING) {\n timeoutStarted = true;\n startTimeout(xhr);\n }\n };\n })(false));\n\n return this;\n }\n\n /**\n * Send a newly created XHR request.\n * @protected\n * @method HttpModule#_sendRequest\n * @param {?*} [data=null] The data to send with the request.\n * @returns {HttpModule}\n */\n _sendRequest(data = null)\n {\n if (this._xhr && this._xhr.readyState == XMLHttpRequest.OPENED) {\n this._xhr.send(data);\n } else {\n console.warn('A request must have been created before sending any data.');\n }\n\n return this;\n }\n\n /**\n * Abort the current request.\n * @protected\n * @method HttpModule#_abort\n * @returns {HttpModule}\n */\n _abort()\n {\n if (this._xhr) {\n this._xhr.abort();\n }\n\n return this;\n }\n\n /**\n * Get the Resource Timing entry associated to the current request.\n * @protected\n * @method HttpModule#_getTimingEntry\n * @param {HttpModule~timingCallback} callback A callback used to send back the timing entry.\n * @returns {HttpModule}\n */\n _getTimingEntry(callback)\n {\n // The Resource Timing entries aren't immediately available once the 'load' event is triggered by an\n // XMLHttpRequest, we must wait for another process tick to check for a refreshed list.\n setTimeout((lastURLToken => {\n return () => {\n // Filter the timing entries to return only the one concerned by the last request made\n let entries = performance.getEntriesByType('resource').filter(function(entry) {\n return ~entry.name.indexOf(lastURLToken);\n });\n\n /**\n * A callback used to send back the timing entry.\n * @private\n * @callback HttpModule~timingCallback\n * @param {PerformanceResourceTiming} entry The Resource Timing entry associated to the current request.\n */\n callback(entries.length ? entries[0] : null);\n };\n })(this._lastURLToken), 0);\n\n return this;\n }\n\n /**\n * Override the requesting status of the module.\n * @protected\n * @method HttpModule#_setRequesting\n * @param {boolean} isRequesting The requesting status.\n * @returns {HttpModule}\n */\n _setRequesting(isRequesting)\n {\n this._requestingOverridden = true;\n this._requesting = isRequesting;\n return this;\n }\n\n}\n","import HttpModule from './HttpModule';\nimport Timing from '../Timing';\nimport {isObject, assignStrict, except} from '../../utils/helpers';\n\n/**\n * @public\n * @typedef {Object} LatencyModule~settingsObject\n * @property {string} [endpoint=./network.php] Where is located your `network.php` file.\n * @property {number} [measures=5] How many measures should be returned.\n * @property {number} [attempts=3] How much attempts to get a valid value should be done for each measure.\n */\n\n/**\n * @class LatencyModule\n * @extends HttpModule\n * @param {LatencyModule~settingsObject} [settings={}] A set of custom settings.\n */\nexport default class LatencyModule extends HttpModule {\n\n constructor(settings = {})\n {\n super('latency');\n\n this._extendDefaultSettings({\n measures: 5,\n attempts: 3\n }).settings(settings);\n\n // Define the object properties\n this._requestsLeft = 0;\n this._attemptsLeft = 0;\n\n this._latencies = [];\n this._requestID = 0;\n\n // Unique labels for each request, exclusively used to make measures.\n this._timingLabels = {\n start: null,\n end: null,\n measure: null\n };\n\n // Measure the latency with the Resource Timing API once the request is finished\n if (Timing.supportsResourceTiming()) {\n this.on('xhr-load', () => this._measure());\n }\n\n // If the browser doesn't support the Resource Timing API, we fallback on a Datetime solution.\n else {\n // Set a mark when the request starts\n this.on('xhr-loadstart', () => Timing.mark(this._timingLabels.start));\n\n // Then make a measure with the previous mark\n this.on('xhr-readystatechange', xhr => this._measure(xhr));\n }\n }\n\n /**\n * Apply a new set of custom settings.\n * @public\n * @method LatencyModule#settings\n * @param {LatencyModule~settingsObject} settings A set of custom settings.\n * @returns {LatencyModule}\n */\n /**\n * Return the current set of settings.\n * @public\n * @method LatencyModule#settings^2\n * @returns {LatencyModule~settingsObject}\n */\n settings(settings = null)\n {\n if (isObject(settings)) {\n return super.settings(assignStrict(settings, {\n delay: 0 // We dont want any timeout during a latency calculation\n }));\n } else {\n return except(super.settings(), ['delay']);\n }\n }\n\n /**\n * Start requesting the server to make measures.\n * @public\n * @method LatencyModule#start\n * @returns {LatencyModule}\n */\n start()\n {\n // Set the number of requests required to establish the network latency. If the browser doesn't support the\n // Resource Timing API, add a request that will be ignored to avoid a longer request due to a possible\n // DNS/whatever fetch.\n let {measures, attempts} = this.settings();\n\n this._requestsLeft = measures;\n this._attemptsLeft = attempts * measures;\n\n if (!Timing.supportsResourceTiming()) {\n this._requestsLeft++;\n this._attemptsLeft++;\n }\n\n // Override the requesting value since a complete latency request consists off multiple ones\n this._setRequesting(true);\n\n this._latencies = [];\n this._nextRequest();\n\n return this;\n }\n\n /**\n * Initiate the next request used for latency measures.\n * @private\n * @method LatencyModule#_nextRequest\n * @param {boolean} [retry=false] Defines if the next request is a retry due to a failing request or not.\n * @returns {LatencyModule}\n */\n _nextRequest(retry = false)\n {\n const reqID = this._requestID++;\n let requestsLeft = retry ? this._requestsLeft : this._requestsLeft--;\n\n if (this._attemptsLeft-- && (requestsLeft || retry)) {\n // Create unique timing labels for the new request\n var labels = this._timingLabels;\n labels.start = `latency-${reqID}-start`;\n labels.end = `latency-${reqID}-end`;\n labels.measure = `latency-${reqID}-measure`;\n\n // Create the new request and send it\n this._newRequest('GET')._sendRequest();\n } else {\n // All the requests are finished, set the requesting status to false.\n this._setRequesting(false);\n\n // If all the requests have been executed, calculate the average latency. Since the _getTimingEntry() method\n // is asynchronous, wait for the next process tick to execute the _end() method, to be sure that all the\n // latencies have been retrieved.\n setTimeout(() => this._end(), 0);\n }\n\n return this;\n }\n\n /**\n * Make latency measures for the last request.\n * @private\n * @method LatencyModule#_measure\n * @param {?XMLHttpRequest} [xhr=null] The concerned XMLHttpRequest if the browser doesn't support the Resource Timing API.\n * @returns {LatencyModule}\n */\n _measure(xhr = null)\n {\n // With Resource Timing API\n if (!xhr) {\n this._getTimingEntry(entry => {\n // The latency calculation differs between an HTTP and an HTTPS connection\n // See: http://www.w3.org/TR/resource-timing/#processing-model\n let latency = !entry.secureConnectionStart\n ? entry.connectEnd - entry.connectStart\n : entry.secureConnectionStart - entry.connectStart;\n\n if (latency) this._latencies.push(latency);\n this._nextRequest(!latency);\n });\n }\n\n // Without Resource Timing API\n else if (this._requestsLeft < this.settings().measures) {\n\n // Measure and save the latency if the headers have been received\n if (xhr.readyState == XMLHttpRequest.HEADERS_RECEIVED) {\n let labels = this._timingLabels;\n\n Timing.mark(labels.end);\n let latency = Timing.measure(labels.measure, labels.start, labels.end);\n\n if (latency) this._latencies.push(latency);\n\n // Abort the current request before we run a new one\n this._abort();\n this._nextRequest(!latency);\n }\n\n }\n\n // Ignore the first request when using the XHR states. See the comments in the start() method for explanations.\n else {\n this._nextRequest();\n }\n\n return this;\n }\n\n /**\n * End the measures.\n * @private\n * @method LatencyModule#_end\n * @returns {LatencyModule}\n */\n _end()\n {\n let latencies = this._latencies;\n\n // Get the average latency\n let avgLatency = latencies.reduce((a, b) => a + b, 0) / (latencies.length || 1);\n avgLatency = avgLatency || null;\n\n // If there is not enough measures, display a warning.\n if (latencies.length < this.settings().measures) {\n let {measures, attempts} = this.settings();\n\n console.warn([\n 'An insufficient number of measures have been processed, this could be due to your web server using',\n `persistant connections or to your client settings (measures: ${measures}, attempts: ${attempts})`\n ].join(' '));\n }\n\n // Trigger the \"end\" event with the average latency and the latency list as parameters\n this.trigger('end', avgLatency, latencies);\n\n return this;\n }\n\n}\n","import EventDispatcher from './EventDispatcher';\nimport HttpModule from './Http/HttpModule';\nimport LatencyModule from './Http/LatencyModule';\nimport BandwidthModule from './Http/BandwidthModule';\nimport Timing from './Timing';\nimport {getGlobalObject, isObject, assign, except} from '../utils/helpers';\n\n/**\n * @public\n * @typedef {Object} Network~settingsObject\n * @property {LatencyModule~settingsObject} latency\n * @property {BandwidthModule~settingsObject} upload\n * @property {BandwidthModule~settingsObject} download\n * @example\n * {\n * // Top-level properties are applied to all the modules\n * endpoint: './my-new-endpoint/',\n *\n * // Top-level properties will be overridden by the ones specified in each module\n * latency: {\n * endpoint: './my-new-latency-endpoint/'\n * }\n * }\n */\n\n/**\n * @class Network\n * @param {Network~settingsObject} [settings={}] A set of custom settings.\n * @member {LatencyModule} latency The latency module.\n * @member {BandwidthModule} upload The upload module.\n * @member {BandwidthModule} download The download module.\n */\nexport default class Network {\n\n /**\n * Expose all the internal classes to the global scope. Only for testing purposes!\n * @private\n * @method Network._exposeInternalClasses\n * @returns {Network}\n */\n static _exposeInternalClasses()\n {\n let global = getGlobalObject(),\n classes = {EventDispatcher, HttpModule, LatencyModule, BandwidthModule, Timing};\n\n Object.keys(classes).forEach(name => {\n global[name] = classes[name];\n });\n\n return this;\n }\n\n constructor(settings = {})\n {\n this._modules = {};\n this._modulesInitialized = false;\n this._pendingSettings = {};\n\n this._registerModule('latency', settings => new LatencyModule(settings))\n ._registerModule('upload', settings => new BandwidthModule('upload', settings))\n ._registerModule('download', settings => new BandwidthModule('download', settings));\n\n this._initModules(this.settings(settings));\n }\n\n /**\n * Apply a new set of custom settings.\n * @public\n * @method Network#settings\n * @param {Network~settingsObject} settings A set of custom settings.\n * @returns {Network}\n */\n /**\n * Return the current set of settings.\n * @public\n * @method Network#settings^2\n * @returns {Network~settingsObject}\n */\n settings(settings = null)\n {\n let moduleNames = Object.keys(this._modules);\n\n if (isObject(settings)) {\n // Extract the global settings\n let globalSettings = except(settings, moduleNames);\n\n // Extract the local settings\n let localSettings = except(settings, Object.keys(globalSettings));\n\n // Create new settings with the global ones nested in the local ones\n settings = moduleNames.reduce((settings, moduleName) => {\n return assign(settings, {[moduleName]: globalSettings});\n }, {});\n\n // Apply the local settings to the new settings\n settings = assign(settings, localSettings);\n\n // Apply the settings to the modules\n if (this._modulesInitialized) {\n Object.keys(this._modules).forEach(name => {\n this._modules[name].settings(settings[name]);\n });\n }\n\n // If the modules aren't instanciated, store the settings.\n else {\n this._pendingSettings = settings;\n }\n\n return this;\n } else {\n return moduleNames.reduce((settings, moduleName) => {\n return assign(settings, {[moduleName]: this._modules[moduleName].settings()});\n }, {});\n }\n }\n\n /**\n * Return if a module is currently making a request.\n * @public\n * @method Network#isRequesting\n * @returns {boolean} `true` if a module is requesting, otherwise `false`.\n */\n isRequesting()\n {\n let requesting = false;\n\n for (let name in this._modules) {\n if (this._modules.hasOwnProperty(name)) {\n requesting = requesting || this._modules[name].isRequesting();\n }\n }\n\n return requesting;\n }\n\n /**\n * Register a new module for the current `Network` instance.\n * @private\n * @method Network#registerModule\n * @param {string} name The name of the module. Will be used to create the property `Network.`.\n * @param {Network~moduleCallback} moduleCallback A callback used to initialize a module with a set of settings.\n * @returns {Network}\n */\n _registerModule(name, moduleCallback)\n {\n /**\n * A callback used to initialize a module with a set of settings.\n * @private\n * @callback Network~moduleCallback\n * @param {Object} settings A set of custom settings.\n * @returns {HttpModule} An instanciated subclass of `HttpModule`.\n */\n this._modules[name] = moduleCallback;\n return this;\n }\n\n /**\n * Initialize all the registered modules with the settings passed to the constructor.\n * @private\n * @method Network#_initModules\n * @returns {Network}\n */\n _initModules()\n {\n if (!this._modulesInitialized) {\n // Initialize the modules with their respective settings\n Object.keys(this._modules).forEach(name => {\n this._modules[name] = this._modules[name](this._pendingSettings[name]).on('_newRequest', () => {\n return !this.isRequesting();\n });\n\n this[name] = this._modules[name];\n });\n\n this._modulesInitialized = true;\n }\n\n return this;\n }\n\n}\n","import {getGlobalObject} from '../utils/helpers';\n\n/**\n * @private\n * @class Timing\n */\nclass Timing {\n\n constructor()\n {\n const global = getGlobalObject();\n\n /**\n * Defines if the current browser supports some specific Timing APIs.\n * @private\n * @member {Object} _support\n * @property {boolean} performance `true` if the Performance API is available.\n * @property {boolean} userTiming `true` if the User Timing API is available.\n * @property {boolean} resourceTiming `true` if the Resource Timing API is available.\n */\n this._support = {\n performance: !!global.performance,\n userTiming: global.performance && performance.mark,\n resourceTiming: global.performance\n && (typeof performance.getEntriesByType == \"function\")\n && performance.timing\n };\n\n /**\n * Contains all the marks created by the `mark` method.\n * @private\n * @member {Object} _marks\n */\n this._marks = {};\n\n /**\n * Contains all the measures created by the `measure` method.\n * @private\n * @member {Object} _measures\n */\n this._measures = {};\n }\n\n /**\n * Create a new timing mark.\n * @public\n * @method Timing#mark\n * @param {string} label A label associated to the mark.\n * @returns {Timing}\n */\n mark(label)\n {\n const support = this._support,\n marks = this._marks;\n\n if (support.userTiming) {\n performance.mark(label);\n }\n\n if (support.performance) {\n marks[label] = performance.now();\n } else {\n marks[label] = (new Date).getTime();\n }\n\n return this;\n }\n\n /**\n * Measure the delay between two marks.\n * @public\n * @method Timing#measure\n * @param {string} measureLabel A label associated to the measure.\n * @param {string} markLabelA The label of the first mark.\n * @param {string} markLabelB The label of the second mark.\n * @returns {number} The measured value.\n */\n measure(measureLabel, markLabelA, markLabelB)\n {\n const support = this._support,\n marks = this._marks,\n measures = this._measures;\n\n if (typeof measures[measureLabel] == 'undefined') {\n const measureWithoutUserTiming = marks[markLabelB] - marks[markLabelA];\n\n if (support.userTiming) {\n performance.measure(measureLabel, markLabelA, markLabelB);\n const entriesByName = performance.getEntriesByName(measureLabel);\n\n // The performance API could return no corresponding entries in Firefox so we must use a fallback.\n // See: https://github.com/nesk/network.js/issues/32#issuecomment-118434305\n measures[measureLabel] = entriesByName.length ? entriesByName[0].duration : measureWithoutUserTiming;\n } else {\n measures[measureLabel] = measureWithoutUserTiming;\n }\n }\n\n return measures[measureLabel];\n }\n\n /**\n * Determine if the current browser supports the Resource Timing API.\n * @public\n * @method Timing#supportsResourceTiming\n * @returns {boolean} `true` if the Resource Timing API is supported, otherwise `false`.\n */\n supportsResourceTiming()\n {\n return this._support.resourceTiming;\n }\n\n}\n\nexport default new Timing();\n","/**\n * Return the global object.\n * @private\n * @function getGlobalObject\n * @return {Object}\n * @see https://gist.github.com/rauschma/1bff02da66472f555c75\n */\nexport function getGlobalObject() {\n // Workers don’t have `window`, only `self`.\n if (typeof self !== 'undefined') {\n return self;\n }\n\n if (typeof global !== 'undefined') {\n return global;\n }\n\n // Not all environments allow `eval` and `Function`, use only as a last resort.\n return new Function('return this')();\n}\n\n/**\n * Determine if the provided value is an object.\n * @private\n * @function isObject\n * @param {*} obj The value to check.\n * @returns {boolean} `true` if the value is an object, otherwise `false`.\n */\nexport function isObject(obj)\n{\n return obj != undefined && obj != null && typeof obj.valueOf() == 'object';\n}\n\n/**\n * Make a deep copy of any value.\n * @private\n * @function copy\n * @param {*} value The value to copy.\n * @returns {*} The copied value.\n */\nexport function copy(value)\n{\n return JSON.parse(JSON.stringify(value));\n}\n\n/**\n * Copy the properties in the source objects over to the destination object.\n * @private\n * @function _assign\n * @param {boolean} strict Given `true`, new properties will not be copied.\n * @param {Object} [target={}] The destination object.\n * @param {...Object} sources The source objects.\n * @returns {Object} The destination object once the properties are copied.\n */\nfunction _assign(strict, target = {}, ...sources)\n{\n target = copy(target);\n\n sources.forEach(source => {\n Object.keys(source).forEach(key => {\n if (!strict || target.hasOwnProperty(key)) {\n let value = source[key];\n target[key] = isObject(value) ? _assign(strict, target[key], value) : value;\n }\n })\n });\n\n return target;\n}\n\n/**\n * Copy all the properties in the source objects over to the destination object.\n * @private\n * @function assign\n * @param {Object} [target={}] The destination object.\n * @param {...Object} sources The source objects.\n * @returns {Object} The destination object once the properties are copied.\n */\nexport function assign(target = {}, ...sources)\n{\n return _assign(false, target, ...sources);\n}\n\n/**\n * Copy the properties (but no new ones) in the source objects over to the destination object.\n * @private\n * @function assignStrict\n * @param {Object} [target={}] The destination object.\n * @param {...Object} sources The source objects.\n * @returns {Object} The destination object once the properties are copied.\n */\nexport function assignStrict(target = {}, ...sources)\n{\n return _assign(true, target, ...sources);\n}\n\n/**\n * Get a copy of an object without some of its properties.\n * @private\n * @function except\n * @param {Object} obj The original object.\n * @param {string[]} properties The properties to exclude from the copied object.\n * @returns {Object} The copied object without the specified properties.\n */\nexport function except(obj, properties)\n{\n let objCopy = copy(obj);\n\n properties.forEach(index => delete objCopy[index]);\n\n return objCopy;\n}\n\n/**\n * Defer the execution of a function.\n * @private\n * @function defer\n * @param {Function} func The function to defer.\n * @returns {Defer} The Defer object used to execute the function when needed.\n */\nexport function defer(func = () => {})\n{\n /**\n * @private\n * @class Defer\n */\n return new class {\n constructor()\n {\n this.func = func;\n }\n\n /**\n * Execute the deferred function.\n * @public\n * @method Defer#run\n */\n run()\n {\n if (this.func) this.func();\n delete this.func;\n }\n };\n}\n"],"sourceRoot":"/source/"}