{"version":3,"sources":["node_modules/browserify/node_modules/browser-pack/_prelude.js","network.js","../lib/Network.js","../lib/EventDispatcher.js","../lib/Http/BandwidthModule.js","../lib/Http/HttpModule.js","../lib/Http/LatencyModule.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,"_interopRequire","obj","__esModule","_defineProperty","key","value","Object","defineProperty","enumerable","configurable","writable","_createClass","defineProperties","target","props","prop","Constructor","protoProps","staticProps","prototype","_classCallCheck","instance","TypeError","EventDispatcher","HttpModule","LatencyModule","BandwidthModule","Timing","_utilsHelpers","isObject","assign","except","settings","undefined","arguments","_modules","_modulesInitialized","_pendingSettings","_registerModule","_initModules","_settings","_settingsWrapper","apply","toString","_this","moduleNames","keys","reduce","moduleName","_ret","globalSettings","localSettings","forEach","name","v","isRequesting","requesting","_name","hasOwnProperty","moduleCallback","on","_exposeInternalClasses","classes","../utils/helpers","./EventDispatcher","./Http/BandwidthModule","./Http/HttpModule","./Http/LatencyModule","./Timing",2,"_eventCallbacks","events","callback","Array","isArray","event","eventCallbacks","indexOf","push","off","callbackIndex","splice","trigger","_len","extraParameters","_key","returnValue","eventCallback",3,"_get","get","object","property","receiver","desc","getOwnPropertyDescriptor","parent","getPrototypeOf","getter","_inherits","subClass","superClass","create","constructor","__proto__","defer","_HttpModule","loadingType","_extendDefaultSettings","data","size","multiplier","_loadingType","_intendedEnd","_isRestarting","_lastLoadedValue","_speedRecords","_avgSpeed","_requestID","_progressID","_started","_firstProgress","_deferredProgress","_timingLabels","start","progress","end","measure","mark","xhr","readyState","XMLHttpRequest","LOADING","eventsPrefix","_progress","_timeout","_end","dataSettings","reqID","labels","blob","Blob","ArrayBuffer","type","_newRequest","_sendRequest","abort","_abort","run","progressID","markLabel","loaded","instantSpeed","avgMeasure","avgSpeed","instantMeasure","../../utils/helpers","../Timing","./HttpModule",4,"_slice","slice","assignStrict","_EventDispatcher","endpoint","delay","_moduleName","_xhr","_lastURLToken","_requestingOverridden","_requesting","_defaultSettings","httpMethod","queryParams","console","warn","validHttpMethods","tokenSuffix","Date","getTime","url","param","encodeURIComponent","open","timeout","OPENED","eventTypes","eventType","addEventListener","concat","upload","send","_getTimingEntry","setTimeout","lastURLToken","entries","performance","getEntriesByType","filter","entry","_setRequesting","../EventDispatcher",5,"measures","attempts","_requestsLeft","_attemptsLeft","_latencies","supportsResourceTiming","_measure","_settings2","_nextRequest","retry","requestsLeft","HEADERS_RECEIVED","latency","secureConnectionStart","connectStart","connectEnd","latencies","avgLatency","b","join",6,"_marks","_measures","_support","userTiming","resourceTiming","timing","label","support","marks","now","measureLabel","markLabelA","markLabelB","getEntriesByName","duration",7,"valueOf","copy","JSON","parse","stringify","_assign","strict","sources","source","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`.\n * @param {Network~moduleCallback} moduleCallback A callback used to initialize a module with a set of settings.\n * @returns {Network}\n */\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 _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\n value: function _initModules() {\n var _this = this;\n\n if (!this._modulesInitialized) {\n // Initialize the modules with their respective settings\n Object.keys(this._modules).forEach(function (name) {\n _this._modules[name] = _this._modules[name](_this._pendingSettings[name]).on(\"_newRequest\", function () {\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 _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\n value: function _exposeInternalClasses() {\n var classes = { EventDispatcher: EventDispatcher, HttpModule: HttpModule, LatencyModule: LatencyModule, BandwidthModule: BandwidthModule, Timing: Timing };\n\n Object.keys(classes).forEach(function (name) {\n window[name] = classes[name];\n });\n\n return this;\n }\n }\n });\n\n return Network;\n})();\n\nmodule.exports = Network;\n\n},{\"../utils/helpers\":7,\"./EventDispatcher\":2,\"./Http/BandwidthModule\":3,\"./Http/HttpModule\":4,\"./Http/LatencyModule\":5,\"./Timing\":6}],2:[function(require,module,exports){\n\"use strict\";\n\nvar _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();\n\nvar _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } };\n\n/**\n * @class EventDispatcher\n */\n\nvar EventDispatcher = (function () {\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 function EventDispatcher() {\n _classCallCheck(this, EventDispatcher);\n\n /**\n * Contains all the event callbacks, organized by events.\n * @private\n * @type {Object}\n */\n this._eventCallbacks = {};\n }\n\n _createClass(EventDispatcher, {\n on: {\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\n value: function on(events, callback) {\n var _this = this;\n\n events = Array.isArray(events) ? events : [events];\n\n events.forEach(function (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 off: {\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\n value: function off(events) {\n var _this = this;\n\n var callback = arguments[1] === undefined ? null : arguments[1];\n\n events = Array.isArray(events) ? events : [events];\n\n events.forEach(function (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 trigger: {\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\n value: function trigger(event) {\n for (var _len = arguments.length, extraParameters = Array(_len > 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\n return EventDispatcher;\n})();\n\nmodule.exports = EventDispatcher;\n\n},{}],3:[function(require,module,exports){\n\"use strict\";\n\nvar _interopRequire = function (obj) { return obj && obj.__esModule ? obj[\"default\"] : obj; };\n\nvar _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();\n\nvar _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if (\"value\" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };\n\nvar _inherits = function (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 _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } };\n\nvar HttpModule = _interopRequire(require(\"./HttpModule\"));\n\nvar Timing = _interopRequire(require(\"../Timing\"));\n\nvar defer = require(\"../../utils/helpers\").defer;\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 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 });\n\n _get(Object.getPrototypeOf(BandwidthModule.prototype), \"constructor\", this).call(this, loadingType, 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 Timing.mark(_this._timingLabels.start);\n });\n this.on(\"xhr-readystatechange\", function (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\", 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 start: {\n\n /**\n * Start requesting the server to make measures.\n * @public\n * @method BandwidthModule#start\n * @returns {BandwidthModule}\n */\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 = 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 abort: {\n\n /**\n * Abort the measures.\n * @public\n * @method BandwidthModule#abort\n * @returns {BandwidthModule}\n */\n\n value: function abort() {\n this._intendedEnd = true;\n return this._abort();\n }\n },\n _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\n value: function _progress(event) {\n var _this = this;\n\n // Ignore the first progress event, it generally contributes to get incoherent values.\n if (this._firstProgress) {\n return this._firstProgress = false;\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(\"\" + 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 = Timing.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 = defer(function () {\n _this._avgSpeed = avgSpeed;\n _this._speedRecords.push(instantSpeed);\n\n _this.trigger(\"progress\", avgSpeed, instantSpeed);\n });\n\n return this;\n }\n },\n _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\n value: function _timeout() {\n this._intendedEnd = true;\n return this;\n }\n },\n _end: {\n\n /**\n * End the measures.\n * @private\n * @method BandwidthModule#_end\n * @returns {BandwidthModule}\n */\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\n return BandwidthModule;\n})(HttpModule);\n\nmodule.exports = BandwidthModule;\n\n},{\"../../utils/helpers\":7,\"../Timing\":6,\"./HttpModule\":4}],4:[function(require,module,exports){\n\"use strict\";\n\nvar _interopRequire = function (obj) { return obj && obj.__esModule ? obj[\"default\"] : obj; };\n\nvar _slice = Array.prototype.slice;\n\nvar _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();\n\nvar _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if (\"value\" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };\n\nvar _inherits = function (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 _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } };\n\nvar EventDispatcher = _interopRequire(require(\"../EventDispatcher\"));\n\nvar _utilsHelpers = require(\"../../utils/helpers\");\n\nvar isObject = _utilsHelpers.isObject;\nvar assign = _utilsHelpers.assign;\nvar assignStrict = _utilsHelpers.assignStrict;\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 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\n value: (function (_settings) {\n var _settingsWrapper = function settings() {\n return _settings.apply(this, arguments);\n };\n\n _settingsWrapper.toString = function () {\n return _settings.toString();\n };\n\n return _settingsWrapper;\n })(function () {\n var settings = arguments[0] === undefined ? null : arguments[0];\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 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\n value: function isRequesting() {\n return this._requesting;\n }\n },\n _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\n value: function _extendDefaultSettings(settings) {\n this._defaultSettings = assign(this._defaultSettings || {}, settings);\n return this;\n }\n },\n _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\n value: function _newRequest(httpMethod, queryParams) {\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 // Define the timeout of the request\n xhr.timeout = settings.delay;\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 self = this,\n eventTypes = [\"loadstart\", \"progress\", \"abort\", \"error\", \"load\", \"timeout\", \"loadend\", \"readystatechange\"];\n\n eventTypes.forEach(function (eventType) {\n xhr.addEventListener(eventType, function () {\n // A last progress event can be triggered once a request has timed out, ignore it.\n if (eventType == \"progress\" && !self._requesting) {\n return;\n }\n\n self.trigger.apply(self, [\"xhr-\" + eventType, xhr].concat(_slice.call(arguments)));\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 self.trigger.apply(self, [\"xhr-upload-\" + eventType, xhr].concat(_slice.call(arguments)));\n });\n }\n });\n\n return this;\n }\n },\n _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\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 _abort: {\n\n /**\n * Abort the current request.\n * @protected\n * @method HttpModule#_abort\n * @returns {HttpModule}\n */\n\n value: function _abort() {\n if (this._xhr) {\n this._xhr.abort();\n }\n\n return this;\n }\n },\n _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\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 _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\n value: function _setRequesting(isRequesting) {\n this._requestingOverridden = true;\n this._requesting = isRequesting;\n return this;\n }\n }\n });\n\n return HttpModule;\n})(EventDispatcher);\n\nmodule.exports = HttpModule;\n\n},{\"../../utils/helpers\":7,\"../EventDispatcher\":2}],5:[function(require,module,exports){\n\"use strict\";\n\nvar _interopRequire = function (obj) { return obj && obj.__esModule ? obj[\"default\"] : obj; };\n\nvar _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();\n\nvar _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if (\"value\" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };\n\nvar _inherits = function (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 _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } };\n\nvar HttpModule = _interopRequire(require(\"./HttpModule\"));\n\nvar Timing = _interopRequire(require(\"../Timing\"));\n\nvar _utilsHelpers = require(\"../../utils/helpers\");\n\nvar isObject = _utilsHelpers.isObject;\nvar assignStrict = _utilsHelpers.assignStrict;\nvar except = _utilsHelpers.except;\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 this._extendDefaultSettings({\n measures: 5,\n attempts: 3\n });\n\n _get(Object.getPrototypeOf(LatencyModule.prototype), \"constructor\", this).call(this, \"latency\");\n\n // Don't use the settings method of parent class but the overridden one in this class\n this.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\", 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 Timing.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 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\n value: (function (_settings) {\n var _settingsWrapper = function settings() {\n return _settings.apply(this, arguments);\n };\n\n _settingsWrapper.toString = function () {\n return _settings.toString();\n };\n\n return _settingsWrapper;\n })(function () {\n var settings = arguments[0] === undefined ? null : arguments[0];\n\n if (isObject(settings)) {\n return _get(Object.getPrototypeOf(LatencyModule.prototype), \"settings\", this).call(this, assignStrict(settings, {\n delay: 0 // We dont want any timeout during a latency calculation\n }));\n } else {\n return except(_get(Object.getPrototypeOf(LatencyModule.prototype), \"settings\", this).call(this), [\"delay\"]);\n }\n })\n },\n start: {\n\n /**\n * Start requesting the server to make measures.\n * @public\n * @method LatencyModule#start\n * @returns {LatencyModule}\n */\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 (!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 _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\n value: function _nextRequest() {\n var _this = 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 _this._end();\n }, 0);\n }\n\n return this;\n }\n },\n _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\n value: function _measure() {\n var _this = 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) _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 var labels = this._timingLabels;\n\n Timing.mark(labels.end);\n var 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 // 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 _end: {\n\n /**\n * End the measures.\n * @private\n * @method LatencyModule#_end\n * @returns {LatencyModule}\n */\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 _settings2 = this.settings();\n\n var measures = _settings2.measures;\n var attempts = _settings2.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\n return LatencyModule;\n})(HttpModule);\n\nmodule.exports = LatencyModule;\n\n},{\"../../utils/helpers\":7,\"../Timing\":6,\"./HttpModule\":4}],6:[function(require,module,exports){\n\"use strict\";\n\nvar _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();\n\nvar _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } };\n\n/**\n * @private\n * @class Timing\n */\n\nvar Timing = (function () {\n function Timing() {\n _classCallCheck(this, Timing);\n\n this._marks = {};\n this._measures = {};\n\n // Does the browser support the following APIs?\n this._support = {\n performance: !!window.performance,\n userTiming: window.performance && performance.mark,\n resourceTiming: window.performance && typeof performance.getEntriesByType == \"function\" && performance.timing\n };\n }\n\n _createClass(Timing, {\n 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\n value: function mark(label) {\n var support = this._support,\n marks = this._marks;\n\n if (support.userTiming) {\n performance.mark(label);\n } else if (support.performance) {\n marks[label] = performance.now();\n } else {\n marks[label] = new Date().getTime();\n }\n\n return this;\n }\n },\n 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\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 if (support.userTiming) {\n performance.measure(measureLabel, markLabelA, markLabelB);\n measures[measureLabel] = performance.getEntriesByName(measureLabel)[0].duration;\n } else {\n measures[measureLabel] = marks[markLabelB] - marks[markLabelA];\n }\n }\n\n return measures[measureLabel];\n }\n },\n 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\n value: function supportsResourceTiming() {\n return this._support.resourceTiming;\n }\n }\n });\n\n return Timing;\n})();\n\nmodule.exports = new Timing();\n\n},{}],7:[function(require,module,exports){\n\"use strict\";\n\nvar _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();\n\nvar _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } };\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 */\nexports.isObject = isObject;\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 */\nexports.copy = copy;\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 */\nexports.assign = assign;\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 */\nexports.assignStrict = assignStrict;\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 */\nexports.except = except;\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 */\nexports.defer = defer;\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nfunction isObject(obj) {\n return obj != undefined && obj != null && typeof obj.valueOf() == \"object\";\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 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 var target = arguments[1] === undefined ? {} : arguments[1];\n\n target = copy(target);\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}\nfunction assign() {\n for (var _len = arguments.length, sources = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n sources[_key - 1] = arguments[_key];\n }\n\n var target = arguments[0] === undefined ? {} : arguments[0];\n\n return _assign.apply(undefined, [false, target].concat(sources));\n}\n\nfunction assignStrict() {\n for (var _len = arguments.length, sources = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n sources[_key - 1] = arguments[_key];\n }\n\n var target = arguments[0] === undefined ? {} : arguments[0];\n\n return _assign.apply(undefined, [true, target].concat(sources));\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\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 () {\n _classCallCheck(this, _class);\n\n this.func = func;\n };\n\n _createClass(_class, {\n run: {\n\n /**\n * Execute the deferred function.\n * @public\n * @method Defer#run\n */\n\n value: function run() {\n if (this.func) this.func();\n delete this.func;\n }\n }\n });\n\n return _class;\n })())();\n}\n\n},{}]},{},[1])(1)\n});\n\n\n//# sourceMappingURL=network.js.map","import EventDispatcher from './EventDispatcher';\nimport HttpModule from './Http/HttpModule';\nimport LatencyModule from './Http/LatencyModule';\nimport BandwidthModule from './Http/BandwidthModule';\nimport Timing from './Timing';\nimport {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 * @property {LatencyModule} latency The latency module.\n * @property {BandwidthModule} upload The upload module.\n * @property {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 var classes = {EventDispatcher, HttpModule, LatencyModule, BandwidthModule, Timing};\n\n Object.keys(classes).forEach(name => {\n window[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","/**\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 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 });\n\n super.constructor(loadingType, 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.constructor();\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 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(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 // Define the timeout of the request\n xhr.timeout = settings.delay;\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 self = this,\n eventTypes = ['loadstart', 'progress', 'abort', 'error', 'load', 'timeout', 'loadend', 'readystatechange'];\n\n eventTypes.forEach(eventType => {\n xhr.addEventListener(eventType, function() {\n // A last progress event can be triggered once a request has timed out, ignore it.\n if (eventType == 'progress' && !self._requesting) {\n return;\n }\n\n self.trigger(`xhr-${eventType}`, xhr, ...arguments);\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 self.trigger(`xhr-upload-${eventType}`, xhr, ...arguments);\n });\n }\n });\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 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 /**\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 this._extendDefaultSettings({\n measures: 5,\n attempts: 3\n });\n\n super.constructor('latency');\n\n // Don't use the settings method of parent class but the overridden one in this class\n this.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","/**\n * @private\n * @class Timing\n */\nclass Timing {\n\n constructor()\n {\n this._marks = {};\n this._measures = {};\n\n // Does the browser support the following APIs?\n this._support = {\n performance: !!window.performance,\n userTiming: window.performance && performance.mark,\n resourceTiming: window.performance\n && (typeof performance.getEntriesByType == \"function\")\n && performance.timing\n };\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 var support = this._support,\n marks = this._marks;\n\n if (support.userTiming) {\n performance.mark(label);\n } else 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 var support = this._support,\n marks = this._marks,\n measures = this._measures;\n\n if (typeof measures[measureLabel] == 'undefined') {\n if (support.userTiming) {\n performance.measure(measureLabel, markLabelA, markLabelB);\n measures[measureLabel] = performance.getEntriesByName(measureLabel)[0].duration;\n } else {\n measures[measureLabel] = marks[markLabelB] - marks[markLabelA];\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 * 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/"}