contains route name and time difference.\n\n var resArray = [];\n var position = communicationsData[0].correlatingid ? 0 : tracePoints.length - 1;\n console.log('position for tracePoints:', position); // iterate over ONE elem in tracePoints, creating a
for every data obj.\n\n for (var _i4 = 0; _i4 < tracePoints[position].length; _i4 += 1) {\n if (_i4 !== tracePoints[position].length - 1) {\n // Calc time difference (when not at the end of array):\n // Convert time str to Date obj w/ new Date(), then get the time difference.\n var _timeDiff = new Date(tracePoints[position][_i4 + 1].timeSent) - new Date(tracePoints[position][_i4].timeSent);\n\n resArray.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"RouteCircle\",\n key: _i4\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"p\", {\n id: \"routeText\"\n }, \"Point \", _i4 + 1, \": \", tracePoints[position][_i4].microservice_name), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"p\", {\n id: \"routeTimeDiff\"\n }, \"Time elapsed: \", _timeDiff, \" ms\")));\n } else {\n // If at the end of array, don't push the timeDiff
to resArray (only push a
w/ name).\n resArray.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"RouteCircle\",\n key: _i4\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"p\", {\n id: \"routeText\"\n }, \"Point \", _i4 + 1, \": \", tracePoints[position][_i4].microservice_name)));\n }\n } // console.log('resArray: ', resArray);\n\n /**** Making a list of avg speed-related data. ********/\n // const avgData = [];\n // Object.entries(avgDataObj).forEach((el, i) => {\n // avgData.push(\n // \n // {el[0]}: {el[1]}\n // \n // )\n // })\n // console.log('avgData (array):', avgData);\n\n /**** Making CATEGORIZED lists of avg speed-related data. ********/\n\n\n var avgTime = [],\n totalTime = [],\n count = [];\n var i = 0; // For unique keys for each //\n\n for (var key in avgDataObj) {\n i += 1;\n\n if (key.endsWith('AvgTime')) {\n avgTime.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"span\", {\n className: \"avgDataDetails\",\n key: i\n }, key.slice(0, -7), \": \", avgDataObj[key], \" ms\"));\n }\n\n if (key.endsWith('TotalTime')) {\n totalTime.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"span\", {\n className: \"avgDataDetails\",\n key: i\n }, key.slice(0, -9), \": \", avgDataObj[key], \" ms\"));\n }\n\n if (key.endsWith('Count')) {\n count.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"span\", {\n className: \"avgDataDetails\",\n key: i\n }, key.slice(0, -5), \": \", avgDataObj[key]));\n }\n } // console.log('avgTime:', avgTime);\n // console.log('totalTime:', totalTime);\n // console.log('count:', count);\n\n /****************/\n\n\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"routeDataArea\"\n }, resArray, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"avgData\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"span\", {\n className: \"avgData-titles\"\n }, \"Average time between points:\"), avgTime, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"span\", {\n className: \"avgData-titles\"\n }, \"Total time between points:\"), totalTime, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"span\", {\n className: \"avgData-titles\"\n }, \"Number of trips between points:\"), count));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (RouteLocations);\n\n//# sourceURL=webpack:///./app/charts/route-trace.jsx?");
/***/ }),
@@ -189,7 +226,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var reac
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_chartjs_2__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-chartjs-2 */ \"./node_modules/react-chartjs-2/es/index.js\");\n/* harmony import */ var _context_DetailsContext__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../context/DetailsContext */ \"./app/context/DetailsContext.js\");\n\n\n\n\nvar SpeedChart = function SpeedChart(props) {\n var healthData = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_DetailsContext__WEBPACK_IMPORTED_MODULE_2__[\"default\"]).detailData;\n\n var createChart = function createChart() {\n var xAxis = [];\n var yAxis = [];\n\n for (var i = 0; i < healthData.length; i += 1) {\n var element = healthData[i]; // If using a SQL Database\n\n if (element.currentmicroservice === props.service && element.cpucurrentspeed) {\n xAxis.push(i);\n yAxis.push(element.cpucurrentspeed);\n } // If using a Mongo Database\n\n\n if (element.currentMicroservice === props.service && element.cpuCurrentSpeed) {\n xAxis.push(i);\n yAxis.push(element.cpuCurrentSpeed);\n }\n }\n\n var chartData = {\n datasets: [{\n label: \"CPU Speed of \".concat(props.service),\n data: yAxis,\n backgroundColor: ['rgb(2, 210, 249)']\n }],\n options: {},\n xAxisID: 'Speed',\n yAxisID: 'Communicaton',\n labels: xAxis\n };\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_chartjs_2__WEBPACK_IMPORTED_MODULE_1__[\"Line\"], {\n data: chartData\n });\n };\n\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, createChart());\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (SpeedChart);\n\n//# sourceURL=webpack:///./app/charts/speed-chart.jsx?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_plotly_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-plotly.js */ \"./node_modules/react-plotly.js/react-plotly.js\");\n/* harmony import */ var react_plotly_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_plotly_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _context_DetailsContext__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../context/DetailsContext */ \"./app/context/DetailsContext.js\");\n\n\n\n\nvar SpeedChart = function SpeedChart(props) {\n var healthData = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_DetailsContext__WEBPACK_IMPORTED_MODULE_2__[\"default\"]).detailData;\n\n var createChart = function createChart() {\n var xAxis = [];\n var yAxis = [];\n\n for (var i = 0; i < healthData.length; i += 1) {\n var element = healthData[i]; // If using a SQL Database\n\n if (element.currentmicroservice === props.service && element.cpucurrentspeed) {\n xAxis.push(i);\n yAxis.push(element.cpucurrentspeed);\n } // If using a Mongo Database\n\n\n if (element.currentMicroservice === props.service && element.cpuCurrentSpeed) {\n xAxis.push(i);\n yAxis.push(element.cpuCurrentSpeed);\n }\n }\n\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_plotly_js__WEBPACK_IMPORTED_MODULE_1___default.a, {\n data: [{\n domain: {\n x: [0, 1],\n y: [0, 1]\n },\n type: 'indicator',\n value: yAxis[yAxis.length - 1],\n title: {\n 'text': \"Speed Chart\"\n },\n delta: {\n 'reference': 3.5,\n 'increasing': {\n 'color': \"mistyrose\"\n }\n },\n mode: \"gauge+number+delta\",\n gauge: {\n axis: {\n range: [null, 8]\n },\n 'tickwidth': 1,\n 'tickcolor': \"#fce38a\",\n 'bar': {\n 'color': \"#6eb6ff\"\n },\n 'bordercolor': \"#a3de83\",\n 'steps': [{\n 'range': [0, 4],\n 'color': '#edf798'\n }, {\n 'range': [4, 6],\n 'color': '#fab57a'\n }],\n 'threshold': {\n 'line': {\n 'color': \"red\",\n 'width': 3.5\n },\n 'thickness': 0.75,\n 'value': 7.5\n }\n }\n }],\n layout: {\n height: 500,\n width: 500,\n paper_bgcolor: '#fffbe0',\n legend: {\n orientation: 'h',\n xanchor: 'center',\n x: .5\n }\n }\n });\n };\n\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, createChart());\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (SpeedChart);\n\n//# sourceURL=webpack:///./app/charts/speed-chart.jsx?");
/***/ }),
@@ -201,7 +238,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var reac
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_chartjs_2__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-chartjs-2 */ \"./node_modules/react-chartjs-2/es/index.js\");\n/* harmony import */ var _context_DetailsContext__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../context/DetailsContext */ \"./app/context/DetailsContext.js\");\n\n\n\n\nvar TemperatureChart = function TemperatureChart(props) {\n var healthData = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_DetailsContext__WEBPACK_IMPORTED_MODULE_2__[\"default\"]).detailData;\n\n var createChart = function createChart() {\n var yAxis = [];\n var xAxis = [];\n\n for (var i = 0; i < healthData.length; i += 1) {\n var element = healthData[i]; // If Mongo\n\n if (element.currentMicroservice === props.service && element.cpuTemperature) {\n yAxis.push(i);\n xAxis.push(element.cpuTemperature);\n } // If SQL\n\n\n if (element.currentmicroservice === props.service && element.cputemperature) {\n yAxis.push(i);\n xAxis.push(element.cputemperature);\n }\n }\n\n var chartData = {\n datasets: [{\n label: 'Temperature Data',\n data: xAxis,\n backgroundColor: ['rgb(2, 210, 249)']\n }],\n labels: yAxis\n };\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_chartjs_2__WEBPACK_IMPORTED_MODULE_1__[\"Line\"], {\n data: chartData\n });\n };\n\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, createChart());\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (TemperatureChart);\n\n//# sourceURL=webpack:///./app/charts/temperature-chart.jsx?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_plotly_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-plotly.js */ \"./node_modules/react-plotly.js/react-plotly.js\");\n/* harmony import */ var react_plotly_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_plotly_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _context_DetailsContext__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../context/DetailsContext */ \"./app/context/DetailsContext.js\");\n\n\n\n\nvar TemperatureChart = function TemperatureChart(props) {\n var healthData = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_DetailsContext__WEBPACK_IMPORTED_MODULE_2__[\"default\"]).detailData;\n\n var createChart = function createChart() {\n var yAxis = [];\n var xAxis = [];\n\n for (var i = 0; i < healthData.length; i += 1) {\n var element = healthData[i]; // If Mongo\n\n if (element.currentMicroservice === props.service && element.cpuTemperature) {\n yAxis.push(i);\n xAxis.push(element.cpuTemperature);\n } // If SQL\n\n\n if (element.currentmicroservice === props.service && element.cputemperature) {\n yAxis.push(i);\n xAxis.push(element.cputemperature);\n }\n }\n\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_plotly_js__WEBPACK_IMPORTED_MODULE_1___default.a, {\n data: [{\n type: 'scatter',\n fill: 'tozeroy',\n fillcolor: 'rgba(224, 62, 54, .6)',\n mode: 'none',\n x: yAxis,\n y: xAxis,\n name: 'CPU Temperature',\n showlegend: true\n }],\n layout: {\n width: 500,\n height: 500,\n paper_bgcolor: '#fffbe0',\n plot_bgcolor: '#fffbe0',\n legend: {\n orientation: 'h',\n xanchor: 'center',\n x: .5\n },\n yaxis: {\n rangemode: 'nonnegative'\n }\n }\n });\n };\n\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, createChart());\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (TemperatureChart);\n\n//# sourceURL=webpack:///./app/charts/temperature-chart.jsx?");
/***/ }),
@@ -213,7 +250,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var reac
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _context_SetupContext__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../context/SetupContext */ \"./app/context/SetupContext.js\");\n/* harmony import */ var _ServicesDashboard_jsx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ServicesDashboard.jsx */ \"./app/components/ServicesDashboard.jsx\");\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === \"[object Arguments]\")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n // import logo from 'app/assets/logo2.png';\n\n\n\n\nvar _window$require = window.require('electron'),\n ipcRenderer = _window$require.ipcRenderer;\n\nvar AddService = function AddService() {\n // Context used to ensure that that this page is only seen when the setup is required. Updated when user adds a database.\n var ChronosSetup = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_SetupContext__WEBPACK_IMPORTED_MODULE_1__[\"default\"]); // Local state created for form entries ONLY.\n\n var _useState = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(''),\n _useState2 = _slicedToArray(_useState, 2),\n dbState = _useState2[0],\n setDbType = _useState2[1];\n\n var _useState3 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(''),\n _useState4 = _slicedToArray(_useState3, 2),\n uriState = _useState4[0],\n setUri = _useState4[1];\n\n var _useState5 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(''),\n _useState6 = _slicedToArray(_useState5, 2),\n labelState = _useState6[0],\n setLabel = _useState6[1]; // Submits data provided by the user to added to the setting file.\n\n\n var onSubmit = function onSubmit() {\n var userSettings = [labelState, dbState, uriState]; // IPC communication used to update settings JSON with user input.\n\n ipcRenderer.send('submit', JSON.stringify(userSettings));\n ChronosSetup.setupRequired = ChronosSetup.toggleSetup(true); // Refresh window after submit.\n\n document.location.reload();\n }; // it is setting the dbState\n\n\n Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useEffect\"])(function () {\n setDbType(document.getElementById('dbType').value);\n }, [dbState, setDbType]);\n var tooltipWriteup = \"Chronos utilizes user-owned databases to store communications and system health data.\\n Please enter a valid connection string to a SQL or noSQL database to begin monitoring.\";\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"mainContainer\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"img\", {\n src: \"app/assets/logo2.png\",\n alt: \"logo\",\n id: \"addServiceLogo\"\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h2\", {\n className: \"signUpHeader\"\n }, \"Enter Your Database Information\", react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"sup\", {\n className: \"tooltip\"\n }, \"\\u24D8\", react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"tooltiptext\"\n }, tooltipWriteup))), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"form\", null, \"Database Type:\", react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"select\", {\n id: \"dbType\",\n onChange: function onChange() {\n return setDbType(document.getElementById('dbType').value);\n }\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"option\", {\n value: \"SQL\"\n }, \"SQL\"), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"option\", {\n value: \"MongoDB\"\n }, \"MongoDB\")), \"Database URI:\", react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"input\", {\n className: \"userInput\",\n id: \"dburi\",\n onChange: function onChange(e) {\n return setUri(e.target.value);\n },\n placeholder: \"Database URI\"\n }), \"Database Name:\", react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"input\", {\n className: \"userInput\",\n id: \"dbname\",\n onChange: function onChange(e) {\n return setLabel(e.target.value);\n },\n type: \"text\",\n placeholder: \"Database Name\"\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: \"submitBtn\",\n type: \"submit\" // Error Handling.\n ,\n onClick: function onClick() {\n if (document.getElementById('dburi').value === '' || document.getElementById('dbname').value === '') {\n alert('Required field missing. Please verify you provided both required items and resubmit form');\n } else {\n onSubmit();\n }\n }\n }, \"Submit\")));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (AddService);\n\n//# sourceURL=webpack:///./app/components/AddService.jsx?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _context_SetupContext__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../context/SetupContext */ \"./app/context/SetupContext.js\");\n/* harmony import */ var _stylesheets_AddService_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../stylesheets/AddService.css */ \"./app/stylesheets/AddService.css\");\n/* harmony import */ var _stylesheets_AddService_css__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_stylesheets_AddService_css__WEBPACK_IMPORTED_MODULE_2__);\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\nfunction _iterableToArrayLimit(arr, i) { if (typeof Symbol === \"undefined\" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n // import logo from 'app/assets/logo2.png';\n\n\n\n\nvar _window$require = window.require('electron'),\n ipcRenderer = _window$require.ipcRenderer;\n\nvar AddService = function AddService() {\n // Context used to ensure that that this page is only seen when the setup is required. Updated when user adds a database.\n var ChronosSetup = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_SetupContext__WEBPACK_IMPORTED_MODULE_1__[\"default\"]); // Local state created for form entries ONLY.\n\n var _useState = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(''),\n _useState2 = _slicedToArray(_useState, 2),\n dbState = _useState2[0],\n setDbType = _useState2[1];\n\n var _useState3 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(''),\n _useState4 = _slicedToArray(_useState3, 2),\n uriState = _useState4[0],\n setUri = _useState4[1];\n\n var _useState5 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(''),\n _useState6 = _slicedToArray(_useState5, 2),\n labelState = _useState6[0],\n setLabel = _useState6[1]; // Submits data provided by the user to added to the setting file.\n\n\n var onSubmit = function onSubmit() {\n var userSettings = [labelState, dbState, uriState]; // IPC communication used to update settings JSON with user input.\n\n ipcRenderer.send('submit', JSON.stringify(userSettings));\n ChronosSetup.setupRequired = ChronosSetup.toggleSetup(true); // Refresh window after submit.\n\n document.location.reload();\n }; // it is setting the dbState\n\n\n Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useEffect\"])(function () {\n setDbType(document.getElementById('dbType').value);\n }, [dbState, setDbType]);\n var tooltipWriteup = \"Chronos utilizes user-owned databases to store communications and system health data.\\n Please enter a valid connection string to a SQL or noSQL database to begin monitoring.\";\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"mainContainer\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"img\", {\n src: \"app/assets/logo2.png\",\n alt: \"logo\",\n id: \"addServiceLogo\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h2\", {\n className: \"signUpHeader\"\n }, \"Enter Your Database Information\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"form\", null, \"Database Type:\", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"select\", {\n id: \"dbType\",\n onChange: function onChange() {\n return setDbType(document.getElementById('dbType').value);\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"option\", {\n value: \"SQL\"\n }, \"SQL\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"option\", {\n value: \"MongoDB\"\n }, \"MongoDB\")), \"Database URI:\", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"input\", {\n className: \"userInput\",\n id: \"dburi\",\n onChange: function onChange(e) {\n return setUri(e.target.value);\n },\n placeholder: \"Database URI\"\n }), \"Database Name:\", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"input\", {\n className: \"userInput\",\n id: \"dbname\",\n onChange: function onChange(e) {\n return setLabel(e.target.value);\n },\n type: \"text\",\n placeholder: \"Database Name\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: \"submitBtn\",\n type: \"submit\" // Error Handling.\n ,\n onClick: function onClick() {\n if (document.getElementById('dburi').value === '' || document.getElementById('dbname').value === '') {\n alert('Required field missing. Please verify you provided both required items and resubmit form');\n } else {\n onSubmit();\n }\n }\n }, \"Submit\")));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (AddService);\n\n//# sourceURL=webpack:///./app/components/AddService.jsx?");
/***/ }),
@@ -225,67 +262,83 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var reac
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _context_DashboardContext__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../context/DashboardContext */ \"./app/context/DashboardContext.js\");\n/* harmony import */ var _context_SetupContext__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../context/SetupContext */ \"./app/context/SetupContext.js\");\n\n\n // Declare a constant ipcRenderer by deconstructing window.require('electron') so that the onDelete function can initialize an IPC Communication \n\nvar _window$require = window.require('electron'),\n ipcRenderer = _window$require.ipcRenderer; // Deletes a Service\n\n\nvar DeleteService = function DeleteService(props) {\n // Declares a constant setup and initialize it to the SetupContext. \n // SetupContext indicates whether or not an initial setup is necessary.\n // An initial setup is necessary when the user has not saved any database to chronos frontend application. \n var setup = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_SetupContext__WEBPACK_IMPORTED_MODULE_2__[\"default\"]); // Declares a variable serviceList and initialize it to the DashboardContext. \n // DashboardContext lists the databases saved by users. \n\n var serviceList = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_DashboardContext__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n /* \n Sends a deleteService request with an index to an ipcMain.on function within the Main.js \n On return, the function reassigns the serviceList variable to the updated services provided within the deleteResponse. If the serviceList equals [\"hard\",\"coded\",\"in\"], then the user has no database saved to the chronos frontend application. If this is true, the function reassigns setup.setupRequired to true by invoking setup.toggleSetup with the argument 'false'. Then the function reloads the application to show the changes made to the services.\n */\n\n var onDelete = function onDelete(index) {\n ipcRenderer.send('deleteService', index);\n ipcRenderer.on('deleteResponse', function (event, services) {\n serviceList = services;\n\n if (serviceList === [\"hard\", \"coded\", \"in\"]) {\n setup.setupRequired = setup.toggleSetup(false);\n }\n\n document.location.reload();\n });\n }; // Declares a constant databaseButtons and initialize it an empty array\n\n\n var databaseButtons = [];\n /* Iterates over the serviceList to create a button for each service. Each button is pushed into the databaseButtons array as the button is created. Each button has an onclick function that invokes the window confirm function with a warning message (ex:'Are you sure you want to delete this service?') and stores the result of invoking confirm into a constant moveForward. If the moveForward is true, then onDelete function is invoked with the index of where the service is stored within the serviceList*/\n\n var _loop = function _loop(i) {\n databaseButtons.push(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: \"microserviceBtn deleteMicroservice\",\n key: \"delete\" + i,\n onClick: function onClick() {\n var moveForward = confirm(\"Are you sure you want to delete \".concat(serviceList[i], \"? \\n If \\\"YES\\\" press the \\\"OK\\\" button, else press the \\\"Cancel\\\" button\"));\n\n if (moveForward) {\n onDelete(i);\n }\n }\n }, serviceList[i]));\n };\n\n for (var i = 0; i < serviceList.length; i++) {\n _loop(i);\n } // returns the title of the page with all of the services that can be deleted as buttons \n\n\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"mainContainer\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h1\", {\n className: \"overviewTitle\"\n }, \"Press on the Database You Want to Delete\"), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"servicesList\"\n }, databaseButtons));\n}; // export the DeleteService function so that it can imported anywhere\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (DeleteService);\n\n//# sourceURL=webpack:///./app/components/DeleteService.jsx?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _context_DashboardContext__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../context/DashboardContext */ \"./app/context/DashboardContext.js\");\n/* harmony import */ var _context_SetupContext__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../context/SetupContext */ \"./app/context/SetupContext.js\");\n/* harmony import */ var _stylesheets_DeleteServices_css__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../stylesheets/DeleteServices.css */ \"./app/stylesheets/DeleteServices.css\");\n/* harmony import */ var _stylesheets_DeleteServices_css__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_stylesheets_DeleteServices_css__WEBPACK_IMPORTED_MODULE_3__);\n\n\n\n // Declare a constant ipcRenderer by deconstructing window.require('electron') so that the onDelete function can initialize an IPC Communication \n\nvar _window$require = window.require('electron'),\n ipcRenderer = _window$require.ipcRenderer; // Deletes a Service\n\n\nvar DeleteService = function DeleteService(props) {\n // Declares a constant setup and initialize it to the SetupContext. \n // SetupContext indicates whether or not an initial setup is necessary.\n // An initial setup is necessary when the user has not saved any database to chronos frontend application. \n var setup = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_SetupContext__WEBPACK_IMPORTED_MODULE_2__[\"default\"]); // Declares a variable serviceList and initialize it to the DashboardContext. \n // DashboardContext lists the databases saved by users. \n\n var serviceList = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_DashboardContext__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n /* \n Sends a deleteService request with an index to an ipcMain.on function within the Main.js \n On return, the function reassigns the serviceList variable to the updated services provided within the deleteResponse. If the serviceList equals [\"hard\",\"coded\",\"in\"], then the user has no database saved to the chronos frontend application. If this is true, the function reassigns setup.setupRequired to true by invoking setup.toggleSetup with the argument 'false'. Then the function reloads the application to show the changes made to the services.\n */\n\n var onDelete = function onDelete(index) {\n ipcRenderer.send('deleteService', index);\n ipcRenderer.on('deleteResponse', function (event, services) {\n serviceList = services;\n\n if (serviceList === [\"hard\", \"coded\", \"in\"]) {\n setup.setupRequired = setup.toggleSetup(false);\n }\n\n document.location.reload();\n });\n }; // Declares a constant databaseButtons and initialize it an empty array\n\n\n var databaseButtons = [];\n /* Iterates over the serviceList to create a button for each service. Each button is pushed into the databaseButtons array as the button is created. Each button has an onclick function that invokes the window confirm function with a warning message (ex:'Are you sure you want to delete this service?') and stores the result of invoking confirm into a constant moveForward. If the moveForward is true, then onDelete function is invoked with the index of where the service is stored within the serviceList*/\n\n var _loop = function _loop(i) {\n databaseButtons.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: \"microserviceBtn deleteMicroservice\",\n key: \"delete\" + i,\n onClick: function onClick() {\n var moveForward = confirm(\"Are you sure you want to delete \".concat(serviceList[i], \"? \\n If \\\"YES\\\" press the \\\"OK\\\" button, else press the \\\"Cancel\\\" button\"));\n\n if (moveForward) {\n onDelete(i);\n }\n }\n }, serviceList[i]));\n };\n\n for (var i = 0; i < serviceList.length; i++) {\n _loop(i);\n } // returns the title of the page with all of the services that can be deleted as buttons \n\n\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"mainContainer\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h1\", {\n className: \"overviewTitle\"\n }, \"Press on the Database You Want to Delete\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"servicesList\"\n }, databaseButtons));\n}; // export the DeleteService function so that it can imported anywhere\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (DeleteService);\n\n//# sourceURL=webpack:///./app/components/DeleteService.jsx?");
/***/ }),
-/***/ "./app/components/Modal.jsx":
-/*!**********************************!*\
- !*** ./app/components/Modal.jsx ***!
- \**********************************/
+/***/ "./app/components/ServiceDetails.jsx":
+/*!*******************************************!*\
+ !*** ./app/components/ServiceDetails.jsx ***!
+ \*******************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _charts_request_type_chart_jsx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../charts/request-type-chart.jsx */ \"./app/charts/request-type-chart.jsx\");\n/* harmony import */ var _charts_response_code_chart_jsx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../charts/response-code-chart.jsx */ \"./app/charts/response-code-chart.jsx\");\n/* harmony import */ var _charts_speed_chart_jsx__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../charts/speed-chart.jsx */ \"./app/charts/speed-chart.jsx\");\n/* harmony import */ var _charts_processes_chart_jsx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../charts/processes-chart.jsx */ \"./app/charts/processes-chart.jsx\");\n/* harmony import */ var _charts_temperature_chart_jsx__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../charts/temperature-chart.jsx */ \"./app/charts/temperature-chart.jsx\");\n/* harmony import */ var _charts_latency_chart_jsx__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../charts/latency-chart.jsx */ \"./app/charts/latency-chart.jsx\");\n/* harmony import */ var _charts_memory_chart_jsx__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../charts/memory-chart.jsx */ \"./app/charts/memory-chart.jsx\");\n/* harmony import */ var _charts_route_trace_jsx__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../charts/route-trace.jsx */ \"./app/charts/route-trace.jsx\");\n/* harmony import */ var _charts_microservice_traffic_jsx__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../charts/microservice-traffic.jsx */ \"./app/charts/microservice-traffic.jsx\");\n\n\n\n\n\n\n\n\n\n\n\nvar Modal = function Modal(props) {\n // Destructuring props to make linter happy\n var modalChart = props.modalChart,\n service = props.service,\n toggleModalDisplay = props.toggleModalDisplay,\n chartTitle = props.chartTitle; // Dictionary used to render proper data chart within Modal component upon rendering\n\n var dict = {\n Request: react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_request_type_chart_jsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n service: service\n }),\n routesImage: react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_route_trace_jsx__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n service: service\n }),\n Response: react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_response_code_chart_jsx__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n service: service\n }),\n Speed: react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_speed_chart_jsx__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n service: service\n }),\n Processes: react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_processes_chart_jsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n service: service\n }),\n Latency: react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_latency_chart_jsx__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n service: service\n }),\n Traffic: react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_microservice_traffic_jsx__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n service: service\n }),\n Temperature: react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_temperature_chart_jsx__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n service: service\n }),\n Memory: react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_memory_chart_jsx__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n service: service\n })\n }; // event.stopPropogation allows the user to interact with the chart as opposed to a click on the\n // chart bubbling out and closing the Modal.\n\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"modalWindow\",\n onClick: function onClick() {\n return toggleModalDisplay(!toggleModalDisplay);\n }\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"modalContent\",\n onClick: function onClick(event) {\n return event.stopPropagation();\n }\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h3\", {\n id: \"chartTitle\"\n }, \"\".concat(service, \" - \").concat(chartTitle)), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n id: \"modalCloseButton\",\n onClick: function onClick() {\n return toggleModalDisplay(!toggleModalDisplay);\n }\n }, \"\\xD7\"), dict[modalChart]));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Modal);\n\n//# sourceURL=webpack:///./app/components/Modal.jsx?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _containers_GraphsContainer_jsx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../containers/GraphsContainer.jsx */ \"./app/containers/GraphsContainer.jsx\");\n/* eslint-disable react/jsx-one-expression-per-line */\n // import Modal from './Modal.jsx';\n\n // Renders charts created with health and communication data for a selected database.\n\nvar ServiceDetails = function ServiceDetails(props) {\n // Renders health info detail buttons\n var service = props.service;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"serviceDetailsContainer\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h3\", {\n id: \"microserviceHealthTitle\"\n }, \"Microservice Health - \", service), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_containers_GraphsContainer_jsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n service: service\n }));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (ServiceDetails);\n\n//# sourceURL=webpack:///./app/components/ServiceDetails.jsx?");
/***/ }),
-/***/ "./app/components/ServiceDetails.jsx":
-/*!*******************************************!*\
- !*** ./app/components/ServiceDetails.jsx ***!
- \*******************************************/
+/***/ "./app/components/Splash.jsx":
+/*!***********************************!*\
+ !*** ./app/components/Splash.jsx ***!
+ \***********************************/
+/*! exports provided: default */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _stylesheets_splash_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../stylesheets/splash.css */ \"./app/stylesheets/splash.css\");\n/* harmony import */ var _stylesheets_splash_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_stylesheets_splash_css__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\nvar _window$require = window.require('electron'),\n ipcRenderer = _window$require.ipcRenderer;\n\nvar Splash = function Splash(props) {\n var toggleSplash = props.toggleSplash; // I know this line is dense. Bear with me...useEffect hook that fires whenever splash\n // component is rendered, which, after 3 seconds fires toggleSplash passing in what ipcMain\n // returns when it receives the 'toggleSplash' message (which will be false boolean). This then\n // toggles the splash state-property inside of the App component which rerenders app and no longer\n // displays the splash page.\n\n Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useEffect\"])(function () {\n setTimeout(function () {\n return toggleSplash(ipcRenderer.sendSync('toggleSplash'));\n }, 3000);\n });\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"splash\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"img\", {\n alt: \"Chronos Logo\",\n src: \"app/assets/icons/icon.png\",\n id: \"splashLogo\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"span\", {\n id: \"splashText\",\n style: {\n fontFamily: 'Baloo Bhaijaan'\n }\n }, \"chronos\"));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Splash);\n\n//# sourceURL=webpack:///./app/components/Splash.jsx?");
+
+/***/ }),
+
+/***/ "./app/containers/DashboardContainer.jsx":
+/*!***********************************************!*\
+ !*** ./app/containers/DashboardContainer.jsx ***!
+ \***********************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _Modal_jsx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Modal.jsx */ \"./app/components/Modal.jsx\");\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === \"[object Arguments]\")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n/* eslint-disable react/jsx-one-expression-per-line */\n\n // Renders charts created with health and communication data for a selected database.\n\nvar ServiceDetails = function ServiceDetails(props) {\n // Renders health info detail buttons\n var service = props.service,\n setDetails = props.setDetails; // Hook used to toggle whether or not the Modal component renders\n\n var _useState = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(false),\n _useState2 = _slicedToArray(_useState, 2),\n modalDisplay = _useState2[0],\n toggleModalDisplay = _useState2[1]; // Hook used to set the chart that the Modal displays. The\n // modalDisplay state is drilled into the Modal component.\n\n\n var _useState3 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(),\n _useState4 = _slicedToArray(_useState3, 2),\n modalChart = _useState4[0],\n setModalChart = _useState4[1]; // Hook used to set the Modal Component title. The \"alt\" attribute\n // is grabbed from the onClick event via event.path[0].alt\n\n\n var _useState5 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(),\n _useState6 = _slicedToArray(_useState5, 2),\n chartTitle = _useState6[0],\n setChartTitle = _useState6[1]; // Dictionary used by the healthInfoButtons loop below\n\n\n var buttonProperties = [{\n id: 'Request',\n alt: 'Request Data',\n src: 'app/assets/pieChart.png'\n }, {\n id: 'Response',\n alt: 'Response Data',\n src: 'app/assets/pieChart.png'\n }, {\n id: 'Speed',\n alt: 'Speed Data',\n src: 'app/assets/speedChart.png'\n }, {\n id: 'Processes',\n alt: 'Processes Data',\n src: 'app/assets/processingChart.png'\n }, {\n id: 'Latency',\n alt: 'Latency Data',\n src: 'app/assets/latencyChart.png'\n }, {\n id: 'Temperature',\n alt: 'Temperature Data',\n src: 'app/assets/tempChart.png'\n }, {\n id: 'Memory',\n alt: 'Memory Data',\n src: 'app/assets/memoryChart.png'\n }]; // Create the Health Info buttons and their associated properties. Each time a button is clicked,\n // setChartTitle will grab a title to render in the Modal component, setModalChart will grab the\n // correct chart to render, and toggleModalDisplay will actually render the Modal display\n\n var healthInfoButtons = [];\n\n for (var i = 0; i < buttonProperties.length; i += 1) {\n healthInfoButtons.push(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"healthChartContainer\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"input\", {\n onClick: function onClick() {\n setChartTitle(event.path[0].alt);\n setModalChart(event.path[0].id);\n toggleModalDisplay(!modalDisplay);\n },\n service: service,\n type: \"image\",\n id: buttonProperties[i].id,\n src: buttonProperties[i].src,\n width: \"60px\",\n alt: buttonProperties[i].alt\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"br\", null), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, buttonProperties[i].id))));\n }\n\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"serviceDetailsContainer\"\n }, modalDisplay ? react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Modal_jsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n chartTitle: chartTitle,\n service: service,\n modalChart: modalChart,\n toggleModalDisplay: toggleModalDisplay,\n onClick: function onClick() {\n toggleModalDisplay(!modalDisplay);\n }\n }) : null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h3\", {\n id: \"microserviceHealthTitle\"\n }, \"Microservice Health - \", service), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"healthGrid\"\n }, healthInfoButtons), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: \"backButton\",\n type: \"button\",\n onClick: function onClick() {\n // document.location.reload()\n setDetails(null);\n }\n }, \"Clear Health Data\"));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (ServiceDetails);\n\n//# sourceURL=webpack:///./app/components/ServiceDetails.jsx?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _MonitoringContainer_jsx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./MonitoringContainer.jsx */ \"./app/containers/MonitoringContainer.jsx\");\n/* harmony import */ var _SideBarContainer_jsx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./SideBarContainer.jsx */ \"./app/containers/SideBarContainer.jsx\");\n/* harmony import */ var _stylesheets_dashboard_css__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../stylesheets/dashboard.css */ \"./app/stylesheets/dashboard.css\");\n/* harmony import */ var _stylesheets_dashboard_css__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_stylesheets_dashboard_css__WEBPACK_IMPORTED_MODULE_3__);\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\nfunction _iterableToArrayLimit(arr, i) { if (typeof Symbol === \"undefined\" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n\n\n\n\n\nvar DashboardContainer = function DashboardContainer() {\n var _useState = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(),\n _useState2 = _slicedToArray(_useState, 2),\n detailsSelected = _useState2[0],\n setDetails = _useState2[1];\n\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"servicesDashboardContainer\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_SideBarContainer_jsx__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n setDetails: setDetails\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"databsaseList\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MonitoringContainer_jsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n detailsSelected: detailsSelected\n })));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (DashboardContainer);\n\n//# sourceURL=webpack:///./app/containers/DashboardContainer.jsx?");
/***/ }),
-/***/ "./app/components/ServiceOverview.jsx":
+/***/ "./app/containers/GraphsContainer.jsx":
/*!********************************************!*\
- !*** ./app/components/ServiceOverview.jsx ***!
+ !*** ./app/containers/GraphsContainer.jsx ***!
\********************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _assets_routeChart_png__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../assets/routeChart.png */ \"./app/assets/routeChart.png\");\n/* harmony import */ var _assets_routeChart_png__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_assets_routeChart_png__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _context_OverviewContext__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../context/OverviewContext */ \"./app/context/OverviewContext.js\");\n/* harmony import */ var _context_DetailsContext__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../context/DetailsContext */ \"./app/context/DetailsContext.js\");\n/* harmony import */ var _ServiceDetails_jsx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ServiceDetails.jsx */ \"./app/components/ServiceDetails.jsx\");\n/* harmony import */ var _Modal_jsx__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Modal.jsx */ \"./app/components/Modal.jsx\");\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === \"[object Arguments]\")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n\n\n\n\n\n\n\nvar _window$require = window.require('electron'),\n ipcRenderer = _window$require.ipcRenderer;\n\nvar ServiceOverview = function ServiceOverview(props) {\n // Overview state used to create service buttons\n var _useState = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])([]),\n _useState2 = _slicedToArray(_useState, 2),\n overviewState = _useState2[0],\n setOverviewState = _useState2[1]; // Details state used to cause rerender on user selection.\n\n\n var _useState3 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(),\n _useState4 = _slicedToArray(_useState3, 2),\n detailsSelected = _useState4[0],\n setDetails = _useState4[1]; // Contexts have data added to them following successful IPC return. Data is later used to create charts.\n\n\n var serviceComponents = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_OverviewContext__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n var healthdata = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_DetailsContext__WEBPACK_IMPORTED_MODULE_3__[\"default\"]); // Only happens when the component mounts.\n\n Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useEffect\"])(function () {\n // IPC communication used to initiate query for information on microservices.\n ipcRenderer.send('overviewRequest', props.index); // IPC listener responsible for retrieving infomation from asynchronous main process message.\n\n ipcRenderer.on('overviewResponse', function (event, data) {\n // Adds to state and context.\n console.log(JSON.parse(data));\n setOverviewState(Object.values(JSON.parse(data)));\n serviceComponents.overviewData = JSON.parse(data);\n });\n }, []);\n console.log('overviewstate: ', overviewState); // Add routes to the display\n // Hook used to toggle whether or not the Modal component renders\n\n var _useState5 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(false),\n _useState6 = _slicedToArray(_useState5, 2),\n modalDisplay = _useState6[0],\n toggleModalDisplay = _useState6[1]; // Hook used to set the chart that the Modal displays. The\n // modalDisplay state is drilled into the Modal component.\n\n\n var _useState7 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(),\n _useState8 = _slicedToArray(_useState7, 2),\n modalChart = _useState8[0],\n setModalChart = _useState8[1]; // Hook used to set the Modal Component title. The \"alt\" attribute\n // is grabbed from the onClick event via event.path[0].alt\n\n\n var _useState9 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(),\n _useState10 = _slicedToArray(_useState9, 2),\n chartTitle = _useState10[0],\n setChartTitle = _useState10[1]; // route button AND traffic button property\n\n\n var routeButtonProperty = {\n traffic: {\n id: 'Traffic',\n alt: 'Microservice Traffic',\n src: 'app/assets/chartModal.png'\n },\n routes: {\n id: 'routesImage',\n alt: 'Route Trace',\n src: _assets_routeChart_png__WEBPACK_IMPORTED_MODULE_1___default.a\n }\n }; // declare routes array to display routes when modal is toggled\n\n var routes = []; // declare traffic array to display traffic when modal is toggled\n\n var traffic = []; // push traffic component logic traffic\n\n traffic.push(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"healthChartContainer\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"input\", {\n onClick: function onClick() {\n setChartTitle(event.path[0].alt);\n setModalChart(event.path[0].id);\n toggleModalDisplay(!modalDisplay);\n },\n type: \"image\",\n id: routeButtonProperty.traffic.id,\n src: routeButtonProperty.traffic.src,\n width: \"60px\",\n alt: routeButtonProperty.traffic.alt\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"br\", null), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n style: {\n color: 'white',\n paddingLeft: '7px'\n }\n }, routeButtonProperty.traffic.id))); // push routes component logic traffic\n\n routes.push(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"healthChartContainer\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"input\", {\n onClick: function onClick() {\n setChartTitle(event.path[0].alt);\n setModalChart(event.path[0].id);\n toggleModalDisplay(!modalDisplay);\n },\n type: \"image\",\n id: routeButtonProperty.routes.id,\n src: \"app/assets/routeChart.png\",\n width: \"60px\",\n alt: routeButtonProperty.routes.alt\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"br\", null), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n style: {\n color: 'white',\n paddingLeft: '7px'\n }\n }, \"Routes\"))); // Filters data received from IPC to the communications database to create a list of the services tracked in the provided database,\n\n var serviceList = function serviceList() {\n // Holds the buttons generated for unique services.\n var componentButtons = []; // Tracks which services already have button created.\n\n var serviceCache = {};\n\n var _loop = function _loop(i) {\n var element = overviewState[i]; // If SQL\n\n if (element.currentmicroservice) {\n if (!(element.currentmicroservice in serviceCache)) {\n var button = react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: \"servicesBtn\",\n currentMicroservice: element.currentmicroservice,\n type: \"button\",\n key: \"serviceItem\".concat(props.index).concat(i),\n onClick: function onClick() {\n // IPC communication used to initiate query for information on microservice health information.\n ipcRenderer.send('detailsRequest', props.index); // IPC listener responsible for retrieving infomation from asynchronous main process message.\n\n ipcRenderer.on('detailsResponse', function (event, data) {\n // Adds returned data to context\n healthdata.detailData = Object.values(JSON.parse(data)); // Updates state. Triggers rerender.\n\n setDetails(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_ServiceDetails_jsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n service: element.currentmicroservice,\n setDetails: setDetails\n }));\n console.log('details selected is: ', detailsSelected);\n });\n }\n }, element.currentmicroservice);\n componentButtons.push(button);\n serviceCache[element.currentmicroservice] = true;\n }\n } else if (element.currentMicroservice) {\n // If Mongo\n if (element.currentMicroservice) {\n if (!(element.currentMicroservice in serviceCache)) {\n var _button = react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: \"servicesBtn\",\n type: \"button\",\n key: \"serviceItem\".concat(props.index).concat(i),\n onClick: function onClick() {\n ipcRenderer.send('detailsRequest', props.index); // IPC listener responsible for retrieving infomation from asynchronous main process message.\n\n ipcRenderer.on('detailsResponse', function (event, data) {\n // Adds returned data to context.\n healthdata.detailData = Object.values(JSON.parse(data)); // Updates state. Triggers rerender.\n\n setDetails(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_ServiceDetails_jsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n service: element.currentMicroservice\n }));\n });\n }\n }, element.currentMicroservice);\n\n componentButtons.push(_button);\n serviceCache[element.currentMicroservice] = true;\n }\n }\n }\n };\n\n for (var i = 0; i < overviewState.length; i += 1) {\n _loop(i);\n } // If there's no data, return 'No data present', else return microservices button\n\n\n if (componentButtons.length === 0) {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"p\", null, \"No data present\");\n }\n\n return componentButtons;\n };\n\n var tooltipWriteup = \"Communications data - Routes and Traffic - is not specific to a single microservice,\\n but combines data from all microservices within a single application network.\";\n var tooltipWriteup2 = 'View and toggle between health data for individual services within your microservice network.';\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"mainContainer\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h1\", {\n className: \"overviewTitle\"\n }, \"Microservices Overview\"), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h2\", null, \"Communications Data\", react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"sup\", {\n className: \"tooltip\"\n }, \"\\u24D8\", react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"tooltiptext\"\n }, tooltipWriteup))), modalDisplay ? react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Modal_jsx__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n chartTitle: chartTitle,\n modalChart: modalChart,\n service: \"\",\n toggleModalDisplay: toggleModalDisplay,\n onClick: function onClick() {\n toggleModalDisplay(!modalDisplay);\n }\n }) : null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"routeAndTrafficDisplay\"\n }, routes, traffic), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"servicesList\"\n }, serviceList(), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"sup\", {\n className: \"tooltip\"\n }, \"\\u24D8\", react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"tooltiptext\"\n }, tooltipWriteup2))), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"br\", null), detailsSelected || null);\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (ServiceOverview);\n\n//# sourceURL=webpack:///./app/components/ServiceOverview.jsx?");
+<<<<<<< HEAD
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _charts_request_type_chart_jsx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../charts/request-type-chart.jsx */ \"./app/charts/request-type-chart.jsx\");\n/* harmony import */ var _charts_response_code_chart_jsx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../charts/response-code-chart.jsx */ \"./app/charts/response-code-chart.jsx\");\n/* harmony import */ var _charts_speed_chart_jsx__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../charts/speed-chart.jsx */ \"./app/charts/speed-chart.jsx\");\n/* harmony import */ var _charts_processes_chart_jsx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../charts/processes-chart.jsx */ \"./app/charts/processes-chart.jsx\");\n/* harmony import */ var _charts_temperature_chart_jsx__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../charts/temperature-chart.jsx */ \"./app/charts/temperature-chart.jsx\");\n/* harmony import */ var _charts_latency_chart_jsx__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../charts/latency-chart.jsx */ \"./app/charts/latency-chart.jsx\");\n/* harmony import */ var _charts_memory_chart_jsx__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../charts/memory-chart.jsx */ \"./app/charts/memory-chart.jsx\");\n/* harmony import */ var _charts_route_trace_jsx__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../charts/route-trace.jsx */ \"./app/charts/route-trace.jsx\");\n/* harmony import */ var _charts_microservice_traffic_jsx__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../charts/microservice-traffic.jsx */ \"./app/charts/microservice-traffic.jsx\");\n/* harmony import */ var _stylesheets_graphs_css__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../stylesheets/graphs.css */ \"./app/stylesheets/graphs.css\");\n/* harmony import */ var _stylesheets_graphs_css__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(_stylesheets_graphs_css__WEBPACK_IMPORTED_MODULE_10__);\n\n\n\n\n\n\n\n\n\n\n\n\nvar GraphsContainer = function GraphsContainer(props) {\n var service = props.service;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"graphsGrid\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_request_type_chart_jsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n service: service\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_route_trace_jsx__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n service: service\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_response_code_chart_jsx__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n service: service\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_speed_chart_jsx__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n service: service\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_processes_chart_jsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n service: service\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_latency_chart_jsx__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n service: service\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_microservice_traffic_jsx__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n service: service\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_temperature_chart_jsx__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n service: service\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_charts_memory_chart_jsx__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n service: service\n }));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (GraphsContainer);\n\n//# sourceURL=webpack:///./app/containers/GraphsContainer.jsx?");
+=======
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _assets_routeChart_png__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../assets/routeChart.png */ \"./app/assets/routeChart.png\");\n/* harmony import */ var _assets_routeChart_png__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_assets_routeChart_png__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _context_OverviewContext__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../context/OverviewContext */ \"./app/context/OverviewContext.js\");\n/* harmony import */ var _context_DetailsContext__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../context/DetailsContext */ \"./app/context/DetailsContext.js\");\n/* harmony import */ var _ServiceDetails_jsx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ServiceDetails.jsx */ \"./app/components/ServiceDetails.jsx\");\n/* harmony import */ var _Modal_jsx__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Modal.jsx */ \"./app/components/Modal.jsx\");\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === \"[object Arguments]\")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n\n\n\n\n\n\n\nvar _window$require = window.require('electron'),\n ipcRenderer = _window$require.ipcRenderer;\n\nvar ServiceOverview = function ServiceOverview(props) {\n // Overview state used to create service buttons\n var _useState = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])([]),\n _useState2 = _slicedToArray(_useState, 2),\n overviewState = _useState2[0],\n setOverviewState = _useState2[1]; // Details state used to cause rerender on user selection.\n\n\n var _useState3 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(),\n _useState4 = _slicedToArray(_useState3, 2),\n detailsSelected = _useState4[0],\n setDetails = _useState4[1]; // Contexts have data added to them following successful IPC return. Data is later used to create charts.\n\n\n var serviceComponents = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_OverviewContext__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n var healthdata = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_DetailsContext__WEBPACK_IMPORTED_MODULE_3__[\"default\"]); // Only happens when the component mounts.\n\n Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useEffect\"])(function () {\n // IPC communication used to initiate query for information on microservices.\n ipcRenderer.send('overviewRequest', props.index); // IPC listener responsible for retrieving infomation from asynchronous main process message.\n\n ipcRenderer.on('overviewResponse', function (event, data) {\n // Adds to state and context.\n console.log(JSON.parse(data));\n setOverviewState(Object.values(JSON.parse(data)));\n serviceComponents.overviewData = JSON.parse(data);\n });\n }, []);\n console.log('overviewstate: ', overviewState); // Add routes to the display\n // Hook used to toggle whether or not the Modal component renders\n\n var _useState5 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(false),\n _useState6 = _slicedToArray(_useState5, 2),\n modalDisplay = _useState6[0],\n toggleModalDisplay = _useState6[1]; // Hook used to set the chart that the Modal displays. The\n // modalDisplay state is drilled into the Modal component.\n\n\n var _useState7 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(),\n _useState8 = _slicedToArray(_useState7, 2),\n modalChart = _useState8[0],\n setModalChart = _useState8[1]; // Hook used to set the Modal Component title. The \"alt\" attribute\n // is grabbed from the onClick event via event.path[0].alt\n\n\n var _useState9 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(),\n _useState10 = _slicedToArray(_useState9, 2),\n chartTitle = _useState10[0],\n setChartTitle = _useState10[1]; // route button AND traffic button property\n\n\n var routeButtonProperty = {\n traffic: {\n id: 'Traffic',\n alt: 'Microservice Traffic',\n src: 'app/assets/chartModal.png'\n },\n routes: {\n id: 'routesImage',\n alt: 'Route Trace',\n src: _assets_routeChart_png__WEBPACK_IMPORTED_MODULE_1___default.a\n }\n }; // declare routes array to display routes when modal is toggled\n\n var routes = []; // declare traffic array to display traffic when modal is toggled\n\n var traffic = []; // push traffic component logic traffic\n\n traffic.push(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"healthChartContainer\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"input\", {\n onClick: function onClick() {\n setChartTitle(event.path[0].alt);\n setModalChart(event.path[0].id);\n toggleModalDisplay(!modalDisplay);\n },\n type: \"image\",\n id: routeButtonProperty.traffic.id,\n src: routeButtonProperty.traffic.src,\n width: \"60px\",\n alt: routeButtonProperty.traffic.alt\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"br\", null), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n style: {\n color: 'black',\n paddingLeft: '7px'\n }\n }, routeButtonProperty.traffic.id))); // push routes component logic traffic\n\n routes.push(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"healthChartContainer\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"input\", {\n onClick: function onClick() {\n setChartTitle(event.path[0].alt);\n setModalChart(event.path[0].id);\n toggleModalDisplay(!modalDisplay);\n },\n type: \"image\",\n id: routeButtonProperty.routes.id,\n src: \"app/assets/routeChart.png\",\n width: \"60px\",\n alt: routeButtonProperty.routes.alt\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"br\", null), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n style: {\n color: 'black',\n paddingLeft: '7px'\n }\n }, \"Routes\"))); // Filters data received from IPC to the communications database to create a list of the services tracked in the provided database,\n\n var serviceList = function serviceList() {\n // Holds the buttons generated for unique services.\n var componentButtons = []; // Tracks which services already have button created.\n\n var serviceCache = {};\n\n var _loop = function _loop(i) {\n var element = overviewState[i]; // If SQL\n\n if (element.currentmicroservice) {\n if (!(element.currentmicroservice in serviceCache)) {\n var button = react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: \"servicesBtn\",\n currentMicroservice: element.currentmicroservice,\n type: \"button\",\n key: \"serviceItem\".concat(props.index).concat(i),\n onClick: function onClick() {\n // IPC communication used to initiate query for information on microservice health information.\n ipcRenderer.send('detailsRequest', props.index); // IPC listener responsible for retrieving infomation from asynchronous main process message.\n\n ipcRenderer.on('detailsResponse', function (event, data) {\n // Adds returned data to context\n healthdata.detailData = Object.values(JSON.parse(data)); // Updates state. Triggers rerender.\n\n setDetails(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_ServiceDetails_jsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n service: element.currentmicroservice,\n setDetails: setDetails\n }));\n console.log('details selected is: ', detailsSelected);\n });\n }\n }, element.currentmicroservice);\n componentButtons.push(button);\n serviceCache[element.currentmicroservice] = true;\n }\n } else if (element.currentMicroservice) {\n // If Mongo\n if (element.currentMicroservice) {\n if (!(element.currentMicroservice in serviceCache)) {\n var _button = react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: \"servicesBtn\",\n type: \"button\",\n key: \"serviceItem\".concat(props.index).concat(i),\n onClick: function onClick() {\n ipcRenderer.send('detailsRequest', props.index); // IPC listener responsible for retrieving infomation from asynchronous main process message.\n\n ipcRenderer.on('detailsResponse', function (event, data) {\n // Adds returned data to context.\n healthdata.detailData = Object.values(JSON.parse(data)); // Updates state. Triggers rerender.\n\n setDetails(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_ServiceDetails_jsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n service: element.currentMicroservice\n }));\n });\n }\n }, element.currentMicroservice);\n\n componentButtons.push(_button);\n serviceCache[element.currentMicroservice] = true;\n }\n }\n }\n };\n\n for (var i = 0; i < overviewState.length; i += 1) {\n _loop(i);\n } // If there's no data, return 'No data present', else return microservices button\n\n\n if (componentButtons.length === 0) {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"p\", null, \"No data present\");\n }\n\n return componentButtons;\n };\n\n var tooltipWriteup = \"Communications data - Routes and Traffic - is not specific to a single microservice,\\n but combines data from all microservices within a single application network.\";\n var tooltipWriteup2 = 'View and toggle between health data for individual services within your microservice network.';\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"mainContainer\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h1\", {\n className: \"overviewTitle\"\n }, \"Microservices Overview\"), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h2\", null, \"Communications Data\", react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"sup\", {\n className: \"tooltip\"\n }, \"\\u24D8\", react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"tooltiptext\"\n }, tooltipWriteup))), modalDisplay ? react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Modal_jsx__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n chartTitle: chartTitle,\n modalChart: modalChart,\n service: \"\",\n toggleModalDisplay: toggleModalDisplay,\n onClick: function onClick() {\n toggleModalDisplay(!modalDisplay);\n }\n }) : null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"routeAndTrafficDisplay\"\n }, routes, traffic), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"servicesList\"\n }, serviceList(), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"sup\", {\n className: \"tooltip\"\n }, \"\\u24D8\", react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"tooltiptext\"\n }, tooltipWriteup2))), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"br\", null), detailsSelected || null);\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (ServiceOverview);\n\n//# sourceURL=webpack:///./app/components/ServiceOverview.jsx?");
+>>>>>>> f44452fa8acda19c6131565d833c41404df7bd4d
/***/ }),
-/***/ "./app/components/ServicesDashboard.jsx":
-/*!**********************************************!*\
- !*** ./app/components/ServicesDashboard.jsx ***!
- \**********************************************/
+/***/ "./app/containers/MonitoringContainer.jsx":
+/*!************************************************!*\
+ !*** ./app/containers/MonitoringContainer.jsx ***!
+ \************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _ServiceOverview_jsx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ServiceOverview.jsx */ \"./app/components/ServiceOverview.jsx\");\n/* harmony import */ var _context_DashboardContext__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../context/DashboardContext */ \"./app/context/DashboardContext.js\");\n/* harmony import */ var _context_SetupContext__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../context/SetupContext */ \"./app/context/SetupContext.js\");\n/* harmony import */ var _AddService_jsx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AddService.jsx */ \"./app/components/AddService.jsx\");\n/* harmony import */ var _DeleteService_jsx__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./DeleteService.jsx */ \"./app/components/DeleteService.jsx\");\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === \"[object Arguments]\")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n/* eslint-disable react/jsx-one-expression-per-line */\n\n\n\n\n\n\n\nvar ServicesDashboard = function ServicesDashboard(props) {\n // Used to toggle setup required if user wants to add a new database.\n var setup = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_SetupContext__WEBPACK_IMPORTED_MODULE_3__[\"default\"]); // List of the databases saved by users to track microservices.\n\n var serviceList = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_DashboardContext__WEBPACK_IMPORTED_MODULE_2__[\"default\"]); // Used to hold the buttons created for each database found in context.\n\n var _useState = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(),\n _useState2 = _slicedToArray(_useState, 2),\n serviceSelected = _useState2[0],\n setSelection = _useState2[1]; // Creates button for each database in dashboard context.\n\n\n var renderServiceList = function renderServiceList(context) {\n var buttonStore = [];\n\n var _loop = function _loop(i) {\n buttonStore.push(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: \"microserviceBtn\",\n type: \"button\",\n key: \"\".concat(i).concat(context[i]),\n onClick: function onClick() {\n setSelection(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_ServiceOverview_jsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n index: i\n }));\n }\n }, context[i]));\n };\n\n for (var i = 0; i < context.length; i += 1) {\n _loop(i);\n }\n\n return buttonStore;\n };\n\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"servicesDashboardContainer\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"left\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"leftTopContainer\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"img\", {\n alt: \"Chronos Logo\",\n src: \"app/assets/icon2Cropped.png\",\n id: \"serviceDashLogo\"\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"left-top\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h2\", {\n className: \"dashboardHeader\"\n }, \"Your Databases\"), renderServiceList(serviceList)), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"left-bottom\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: \"overviewSubmitBtn\",\n type: \"submit\",\n key: \"BackToStart\",\n onClick: function onClick() {\n setup.setupRequired = setup.toggleSetup(false);\n setSelection(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_AddService_jsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"], null));\n }\n }, \"Add Database\"), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: \"overviewSubmitBtn\",\n type: \"submit\",\n key: \"goToDeletePage\",\n onClick: function onClick() {\n setSelection(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_DeleteService_jsx__WEBPACK_IMPORTED_MODULE_5__[\"default\"], null));\n }\n }, \"Delete Database\")), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"left-bottom\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: \"overviewSubmitBtn\",\n type: \"submit\",\n onClick: function onClick() {\n location.reload();\n }\n }, \"Refresh overview\")))), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"databsaseList\"\n }, serviceSelected));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (ServicesDashboard);\n\n//# sourceURL=webpack:///./app/components/ServicesDashboard.jsx?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n\n\nvar MonitoringContainer = function MonitoringContainer(props) {\n var detailsSelected = props.detailsSelected;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"mainContainer\"\n }, detailsSelected || null);\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (MonitoringContainer);\n\n//# sourceURL=webpack:///./app/containers/MonitoringContainer.jsx?");
/***/ }),
-/***/ "./app/components/Splash.jsx":
-/*!***********************************!*\
- !*** ./app/components/Splash.jsx ***!
- \***********************************/
+/***/ "./app/containers/SideBarContainer.jsx":
+/*!*********************************************!*\
+ !*** ./app/containers/SideBarContainer.jsx ***!
+ \*********************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n\n\nvar _window$require = window.require('electron'),\n ipcRenderer = _window$require.ipcRenderer;\n\nvar Splash = function Splash(props) {\n var toggleSplash = props.toggleSplash; // I know this line is dense. Bear with me...useEffect hook that fires whenever splash\n // component is rendered, which, after 3 seconds fires toggleSplash passing in what ipcMain\n // returns when it receives the 'toggleSplash' message (which will be false boolean). This then\n // toggles the splash state-property inside of the App component which rerenders app and no longer\n // displays the splash page.\n\n Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useEffect\"])(function () {\n setTimeout(function () {\n return toggleSplash(ipcRenderer.sendSync('toggleSplash'));\n }, 3000);\n });\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"splash\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"img\", {\n alt: \"Chronos Logo\",\n src: \"app/assets/icons/icon.png\",\n id: \"splashLogo\"\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"span\", {\n id: \"splashText\",\n style: {\n fontFamily: 'Baloo Bhaijaan'\n }\n }, \"chronos\"));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Splash);\n\n//# sourceURL=webpack:///./app/components/Splash.jsx?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _AComp_SidebarHeader_jsx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../AComp/SidebarHeader.jsx */ \"./app/AComp/SidebarHeader.jsx\");\n/* harmony import */ var _AComp_Extras_jsx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../AComp/Extras.jsx */ \"./app/AComp/Extras.jsx\");\n/* harmony import */ var _context_SetupContext__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../context/SetupContext */ \"./app/context/SetupContext.js\");\n/* harmony import */ var _context_DashboardContext__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../context/DashboardContext */ \"./app/context/DashboardContext.js\");\n/* harmony import */ var _AComp_Microservices_jsx__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../AComp/Microservices.jsx */ \"./app/AComp/Microservices.jsx\");\n/* harmony import */ var _AComp_ServicesList_jsx__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../AComp/ServicesList.jsx */ \"./app/AComp/ServicesList.jsx\");\n/* harmony import */ var _components_AddService_jsx__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../components/AddService.jsx */ \"./app/components/AddService.jsx\");\n/* harmony import */ var _components_DeleteService_jsx__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../components/DeleteService.jsx */ \"./app/components/DeleteService.jsx\");\n/* harmony import */ var _stylesheets_sidebar_css__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../stylesheets/sidebar.css */ \"./app/stylesheets/sidebar.css\");\n/* harmony import */ var _stylesheets_sidebar_css__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(_stylesheets_sidebar_css__WEBPACK_IMPORTED_MODULE_9__);\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\nfunction _iterableToArrayLimit(arr, i) { if (typeof Symbol === \"undefined\" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n\n\n\n\n\n\n\n\n\n\n\nvar SidebarContainer = function SidebarContainer(props) {\n var setDetails = props.setDetails; // Used to toggle setup required if user wants to add a new database.\n\n var setup = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_SetupContext__WEBPACK_IMPORTED_MODULE_3__[\"default\"]); // List of the databases saved by users to track microservices.\n\n var serviceList = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_DashboardContext__WEBPACK_IMPORTED_MODULE_4__[\"default\"]); // Setting index of service selected\n\n var _useState = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(),\n _useState2 = _slicedToArray(_useState, 2),\n index = _useState2[0],\n setIndex = _useState2[1]; // Checking to see if service clicked to display Microservices\n\n\n var _useState3 = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])('false'),\n _useState4 = _slicedToArray(_useState3, 2),\n isclicked = _useState4[0],\n setClicked = _useState4[1]; // Helper function to check if Clicked toggles\n\n\n var clickToggle = function clickToggle() {\n if (isclicked === 'true') setClicked('false');else setClicked('true');\n }; // Click function for Services\n\n\n var ServicesClick = function ServicesClick(e) {\n clickToggle(e);\n setIndex(e.target.id);\n setDetails(null); // setSelection( );\n }; // Click function for AddService\n\n\n var AddClick = function AddClick() {\n setup.setupRequired = setup.toggleSetup(false);\n setDetails( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_AddService_jsx__WEBPACK_IMPORTED_MODULE_7__[\"default\"], null));\n }; // Click fn for Delete Service\n\n\n var DeleteClick = function DeleteClick() {\n setDetails( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_DeleteService_jsx__WEBPACK_IMPORTED_MODULE_8__[\"default\"], null));\n }; // Click fn for Refresh\n\n\n var RefreshClick = function RefreshClick() {\n location.reload();\n };\n\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"left\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"leftTopContainer\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_AComp_SidebarHeader_jsx__WEBPACK_IMPORTED_MODULE_1__[\"default\"], null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_AComp_ServicesList_jsx__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n context: serviceList,\n Click: ServicesClick,\n isclicked: isclicked\n }), isclicked === 'true' ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_AComp_Microservices_jsx__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n index: index,\n setDetails: setDetails\n }) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_AComp_Extras_jsx__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n AddClick: AddClick,\n DeleteClick: DeleteClick,\n RefreshClick: RefreshClick\n })));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (SidebarContainer);\n\n//# sourceURL=webpack:///./app/containers/SideBarContainer.jsx?");
/***/ }),
@@ -337,17 +390,6 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ }),
-/***/ "./app/index.css":
-/*!***********************!*\
- !*** ./app/index.css ***!
- \***********************/
-/*! no static exports found */
-/***/ (function(module, exports, __webpack_require__) {
-
-eval("var content = __webpack_require__(/*! !../node_modules/css-loader/dist/cjs.js!./index.css */ \"./node_modules/css-loader/dist/cjs.js!./app/index.css\");\n\nif (typeof content === 'string') {\n content = [[module.i, content, '']];\n}\n\nvar options = {}\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = __webpack_require__(/*! ../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ \"./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n\n\n//# sourceURL=webpack:///./app/index.css?");
-
-/***/ }),
-
/***/ "./app/index.js":
/*!**********************!*\
!*** ./app/index.js ***!
@@ -356,3024 +398,385 @@ eval("var content = __webpack_require__(/*! !../node_modules/css-loader/dist/cjs
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-dom */ \"./node_modules/react-dom/index.js\");\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _context_SetupContext_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./context/SetupContext.js */ \"./app/context/SetupContext.js\");\n/* harmony import */ var _index_css__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./index.css */ \"./app/index.css\");\n/* harmony import */ var _index_css__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_index_css__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _components_AddService_jsx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./components/AddService.jsx */ \"./app/components/AddService.jsx\");\n/* harmony import */ var _components_ServicesDashboard_jsx__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./components/ServicesDashboard.jsx */ \"./app/components/ServicesDashboard.jsx\");\n/* harmony import */ var _components_Splash_jsx__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./components/Splash.jsx */ \"./app/components/Splash.jsx\");\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); }\n\nfunction _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === \"[object Arguments]\")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n\n\n\n\n\n\n\n\nvar App = function App() {\n var chronosSetup = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_SetupContext_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]); // useState hook to conditionally render the splash page only once per session\n\n var _useState = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(chronosSetup.splash),\n _useState2 = _slicedToArray(_useState, 2),\n splash = _useState2[0],\n toggleSplash = _useState2[1];\n\n if (splash) return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_Splash_jsx__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n toggleSplash: toggleSplash\n });\n return chronosSetup.setupRequired ? react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_AddService_jsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"], null) : react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_ServicesDashboard_jsx__WEBPACK_IMPORTED_MODULE_5__[\"default\"], null);\n};\n\nreact_dom__WEBPACK_IMPORTED_MODULE_1___default.a.render(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(App, null), document.getElementById('app'));\n\n//# sourceURL=webpack:///./app/index.js?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-dom */ \"./node_modules/react-dom/index.js\");\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _context_SetupContext_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./context/SetupContext.js */ \"./app/context/SetupContext.js\");\n/* harmony import */ var _components_AddService_jsx__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./components/AddService.jsx */ \"./app/components/AddService.jsx\");\n/* harmony import */ var _components_Splash_jsx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./components/Splash.jsx */ \"./app/components/Splash.jsx\");\n/* harmony import */ var _containers_DashboardContainer_jsx__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./containers/DashboardContainer.jsx */ \"./app/containers/DashboardContainer.jsx\");\n/* harmony import */ var _stylesheets_index_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./stylesheets/index.css */ \"./app/stylesheets/index.css\");\n/* harmony import */ var _stylesheets_index_css__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_stylesheets_index_css__WEBPACK_IMPORTED_MODULE_6__);\nfunction _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }\n\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\nfunction _iterableToArrayLimit(arr, i) { if (typeof Symbol === \"undefined\" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"] != null) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; }\n\nfunction _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }\n\n\n\n\n\n\n\n\n\nvar App = function App() {\n var chronosSetup = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useContext\"])(_context_SetupContext_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]); // useState hook to conditionally render the splash page only once per session\n\n var _useState = Object(react__WEBPACK_IMPORTED_MODULE_0__[\"useState\"])(chronosSetup.splash),\n _useState2 = _slicedToArray(_useState, 2),\n splash = _useState2[0],\n toggleSplash = _useState2[1];\n\n if (splash) return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_Splash_jsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n toggleSplash: toggleSplash\n });\n return chronosSetup.setupRequired ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_AddService_jsx__WEBPACK_IMPORTED_MODULE_3__[\"default\"], null) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_containers_DashboardContainer_jsx__WEBPACK_IMPORTED_MODULE_5__[\"default\"], null);\n};\n\nreact_dom__WEBPACK_IMPORTED_MODULE_1___default.a.render( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(App, null), document.getElementById('app'));\n\n//# sourceURL=webpack:///./app/index.js?");
/***/ }),
-/***/ "./node_modules/chart.js/dist/Chart.js":
-/*!*********************************************!*\
- !*** ./node_modules/chart.js/dist/Chart.js ***!
- \*********************************************/
+/***/ "./app/stylesheets/AddService.css":
+/*!****************************************!*\
+ !*** ./app/stylesheets/AddService.css ***!
+ \****************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
-eval("/*!\n * Chart.js v2.9.3\n * https://www.chartjs.org\n * (c) 2019 Chart.js Contributors\n * Released under the MIT License\n */\n(function (global, factory) {\n true ? module.exports = factory(function () {\n try {\n return __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n } catch (e) {}\n }()) : undefined;\n})(this, function (moment) {\n 'use strict';\n\n moment = moment && moment.hasOwnProperty('default') ? moment['default'] : moment;\n\n function createCommonjsModule(fn, module) {\n return module = {\n exports: {}\n }, fn(module, module.exports), module.exports;\n }\n\n function getCjsExportFromNamespace(n) {\n return n && n['default'] || n;\n }\n\n var colorName = {\n \"aliceblue\": [240, 248, 255],\n \"antiquewhite\": [250, 235, 215],\n \"aqua\": [0, 255, 255],\n \"aquamarine\": [127, 255, 212],\n \"azure\": [240, 255, 255],\n \"beige\": [245, 245, 220],\n \"bisque\": [255, 228, 196],\n \"black\": [0, 0, 0],\n \"blanchedalmond\": [255, 235, 205],\n \"blue\": [0, 0, 255],\n \"blueviolet\": [138, 43, 226],\n \"brown\": [165, 42, 42],\n \"burlywood\": [222, 184, 135],\n \"cadetblue\": [95, 158, 160],\n \"chartreuse\": [127, 255, 0],\n \"chocolate\": [210, 105, 30],\n \"coral\": [255, 127, 80],\n \"cornflowerblue\": [100, 149, 237],\n \"cornsilk\": [255, 248, 220],\n \"crimson\": [220, 20, 60],\n \"cyan\": [0, 255, 255],\n \"darkblue\": [0, 0, 139],\n \"darkcyan\": [0, 139, 139],\n \"darkgoldenrod\": [184, 134, 11],\n \"darkgray\": [169, 169, 169],\n \"darkgreen\": [0, 100, 0],\n \"darkgrey\": [169, 169, 169],\n \"darkkhaki\": [189, 183, 107],\n \"darkmagenta\": [139, 0, 139],\n \"darkolivegreen\": [85, 107, 47],\n \"darkorange\": [255, 140, 0],\n \"darkorchid\": [153, 50, 204],\n \"darkred\": [139, 0, 0],\n \"darksalmon\": [233, 150, 122],\n \"darkseagreen\": [143, 188, 143],\n \"darkslateblue\": [72, 61, 139],\n \"darkslategray\": [47, 79, 79],\n \"darkslategrey\": [47, 79, 79],\n \"darkturquoise\": [0, 206, 209],\n \"darkviolet\": [148, 0, 211],\n \"deeppink\": [255, 20, 147],\n \"deepskyblue\": [0, 191, 255],\n \"dimgray\": [105, 105, 105],\n \"dimgrey\": [105, 105, 105],\n \"dodgerblue\": [30, 144, 255],\n \"firebrick\": [178, 34, 34],\n \"floralwhite\": [255, 250, 240],\n \"forestgreen\": [34, 139, 34],\n \"fuchsia\": [255, 0, 255],\n \"gainsboro\": [220, 220, 220],\n \"ghostwhite\": [248, 248, 255],\n \"gold\": [255, 215, 0],\n \"goldenrod\": [218, 165, 32],\n \"gray\": [128, 128, 128],\n \"green\": [0, 128, 0],\n \"greenyellow\": [173, 255, 47],\n \"grey\": [128, 128, 128],\n \"honeydew\": [240, 255, 240],\n \"hotpink\": [255, 105, 180],\n \"indianred\": [205, 92, 92],\n \"indigo\": [75, 0, 130],\n \"ivory\": [255, 255, 240],\n \"khaki\": [240, 230, 140],\n \"lavender\": [230, 230, 250],\n \"lavenderblush\": [255, 240, 245],\n \"lawngreen\": [124, 252, 0],\n \"lemonchiffon\": [255, 250, 205],\n \"lightblue\": [173, 216, 230],\n \"lightcoral\": [240, 128, 128],\n \"lightcyan\": [224, 255, 255],\n \"lightgoldenrodyellow\": [250, 250, 210],\n \"lightgray\": [211, 211, 211],\n \"lightgreen\": [144, 238, 144],\n \"lightgrey\": [211, 211, 211],\n \"lightpink\": [255, 182, 193],\n \"lightsalmon\": [255, 160, 122],\n \"lightseagreen\": [32, 178, 170],\n \"lightskyblue\": [135, 206, 250],\n \"lightslategray\": [119, 136, 153],\n \"lightslategrey\": [119, 136, 153],\n \"lightsteelblue\": [176, 196, 222],\n \"lightyellow\": [255, 255, 224],\n \"lime\": [0, 255, 0],\n \"limegreen\": [50, 205, 50],\n \"linen\": [250, 240, 230],\n \"magenta\": [255, 0, 255],\n \"maroon\": [128, 0, 0],\n \"mediumaquamarine\": [102, 205, 170],\n \"mediumblue\": [0, 0, 205],\n \"mediumorchid\": [186, 85, 211],\n \"mediumpurple\": [147, 112, 219],\n \"mediumseagreen\": [60, 179, 113],\n \"mediumslateblue\": [123, 104, 238],\n \"mediumspringgreen\": [0, 250, 154],\n \"mediumturquoise\": [72, 209, 204],\n \"mediumvioletred\": [199, 21, 133],\n \"midnightblue\": [25, 25, 112],\n \"mintcream\": [245, 255, 250],\n \"mistyrose\": [255, 228, 225],\n \"moccasin\": [255, 228, 181],\n \"navajowhite\": [255, 222, 173],\n \"navy\": [0, 0, 128],\n \"oldlace\": [253, 245, 230],\n \"olive\": [128, 128, 0],\n \"olivedrab\": [107, 142, 35],\n \"orange\": [255, 165, 0],\n \"orangered\": [255, 69, 0],\n \"orchid\": [218, 112, 214],\n \"palegoldenrod\": [238, 232, 170],\n \"palegreen\": [152, 251, 152],\n \"paleturquoise\": [175, 238, 238],\n \"palevioletred\": [219, 112, 147],\n \"papayawhip\": [255, 239, 213],\n \"peachpuff\": [255, 218, 185],\n \"peru\": [205, 133, 63],\n \"pink\": [255, 192, 203],\n \"plum\": [221, 160, 221],\n \"powderblue\": [176, 224, 230],\n \"purple\": [128, 0, 128],\n \"rebeccapurple\": [102, 51, 153],\n \"red\": [255, 0, 0],\n \"rosybrown\": [188, 143, 143],\n \"royalblue\": [65, 105, 225],\n \"saddlebrown\": [139, 69, 19],\n \"salmon\": [250, 128, 114],\n \"sandybrown\": [244, 164, 96],\n \"seagreen\": [46, 139, 87],\n \"seashell\": [255, 245, 238],\n \"sienna\": [160, 82, 45],\n \"silver\": [192, 192, 192],\n \"skyblue\": [135, 206, 235],\n \"slateblue\": [106, 90, 205],\n \"slategray\": [112, 128, 144],\n \"slategrey\": [112, 128, 144],\n \"snow\": [255, 250, 250],\n \"springgreen\": [0, 255, 127],\n \"steelblue\": [70, 130, 180],\n \"tan\": [210, 180, 140],\n \"teal\": [0, 128, 128],\n \"thistle\": [216, 191, 216],\n \"tomato\": [255, 99, 71],\n \"turquoise\": [64, 224, 208],\n \"violet\": [238, 130, 238],\n \"wheat\": [245, 222, 179],\n \"white\": [255, 255, 255],\n \"whitesmoke\": [245, 245, 245],\n \"yellow\": [255, 255, 0],\n \"yellowgreen\": [154, 205, 50]\n };\n var conversions = createCommonjsModule(function (module) {\n /* MIT license */\n // NOTE: conversions should only return primitive values (i.e. arrays, or\n // values that give correct `typeof` results).\n // do not use box values types (i.e. Number(), String(), etc.)\n var reverseKeywords = {};\n\n for (var key in colorName) {\n if (colorName.hasOwnProperty(key)) {\n reverseKeywords[colorName[key]] = key;\n }\n }\n\n var convert = module.exports = {\n rgb: {\n channels: 3,\n labels: 'rgb'\n },\n hsl: {\n channels: 3,\n labels: 'hsl'\n },\n hsv: {\n channels: 3,\n labels: 'hsv'\n },\n hwb: {\n channels: 3,\n labels: 'hwb'\n },\n cmyk: {\n channels: 4,\n labels: 'cmyk'\n },\n xyz: {\n channels: 3,\n labels: 'xyz'\n },\n lab: {\n channels: 3,\n labels: 'lab'\n },\n lch: {\n channels: 3,\n labels: 'lch'\n },\n hex: {\n channels: 1,\n labels: ['hex']\n },\n keyword: {\n channels: 1,\n labels: ['keyword']\n },\n ansi16: {\n channels: 1,\n labels: ['ansi16']\n },\n ansi256: {\n channels: 1,\n labels: ['ansi256']\n },\n hcg: {\n channels: 3,\n labels: ['h', 'c', 'g']\n },\n apple: {\n channels: 3,\n labels: ['r16', 'g16', 'b16']\n },\n gray: {\n channels: 1,\n labels: ['gray']\n }\n }; // hide .channels and .labels properties\n\n for (var model in convert) {\n if (convert.hasOwnProperty(model)) {\n if (!('channels' in convert[model])) {\n throw new Error('missing channels property: ' + model);\n }\n\n if (!('labels' in convert[model])) {\n throw new Error('missing channel labels property: ' + model);\n }\n\n if (convert[model].labels.length !== convert[model].channels) {\n throw new Error('channel and label counts mismatch: ' + model);\n }\n\n var channels = convert[model].channels;\n var labels = convert[model].labels;\n delete convert[model].channels;\n delete convert[model].labels;\n Object.defineProperty(convert[model], 'channels', {\n value: channels\n });\n Object.defineProperty(convert[model], 'labels', {\n value: labels\n });\n }\n }\n\n convert.rgb.hsl = function (rgb) {\n var r = rgb[0] / 255;\n var g = rgb[1] / 255;\n var b = rgb[2] / 255;\n var min = Math.min(r, g, b);\n var max = Math.max(r, g, b);\n var delta = max - min;\n var h;\n var s;\n var l;\n\n if (max === min) {\n h = 0;\n } else if (r === max) {\n h = (g - b) / delta;\n } else if (g === max) {\n h = 2 + (b - r) / delta;\n } else if (b === max) {\n h = 4 + (r - g) / delta;\n }\n\n h = Math.min(h * 60, 360);\n\n if (h < 0) {\n h += 360;\n }\n\n l = (min + max) / 2;\n\n if (max === min) {\n s = 0;\n } else if (l <= 0.5) {\n s = delta / (max + min);\n } else {\n s = delta / (2 - max - min);\n }\n\n return [h, s * 100, l * 100];\n };\n\n convert.rgb.hsv = function (rgb) {\n var rdif;\n var gdif;\n var bdif;\n var h;\n var s;\n var r = rgb[0] / 255;\n var g = rgb[1] / 255;\n var b = rgb[2] / 255;\n var v = Math.max(r, g, b);\n var diff = v - Math.min(r, g, b);\n\n var diffc = function (c) {\n return (v - c) / 6 / diff + 1 / 2;\n };\n\n if (diff === 0) {\n h = s = 0;\n } else {\n s = diff / v;\n rdif = diffc(r);\n gdif = diffc(g);\n bdif = diffc(b);\n\n if (r === v) {\n h = bdif - gdif;\n } else if (g === v) {\n h = 1 / 3 + rdif - bdif;\n } else if (b === v) {\n h = 2 / 3 + gdif - rdif;\n }\n\n if (h < 0) {\n h += 1;\n } else if (h > 1) {\n h -= 1;\n }\n }\n\n return [h * 360, s * 100, v * 100];\n };\n\n convert.rgb.hwb = function (rgb) {\n var r = rgb[0];\n var g = rgb[1];\n var b = rgb[2];\n var h = convert.rgb.hsl(rgb)[0];\n var w = 1 / 255 * Math.min(r, Math.min(g, b));\n b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));\n return [h, w * 100, b * 100];\n };\n\n convert.rgb.cmyk = function (rgb) {\n var r = rgb[0] / 255;\n var g = rgb[1] / 255;\n var b = rgb[2] / 255;\n var c;\n var m;\n var y;\n var k;\n k = Math.min(1 - r, 1 - g, 1 - b);\n c = (1 - r - k) / (1 - k) || 0;\n m = (1 - g - k) / (1 - k) || 0;\n y = (1 - b - k) / (1 - k) || 0;\n return [c * 100, m * 100, y * 100, k * 100];\n };\n /**\n * See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance\n * */\n\n\n function comparativeDistance(x, y) {\n return Math.pow(x[0] - y[0], 2) + Math.pow(x[1] - y[1], 2) + Math.pow(x[2] - y[2], 2);\n }\n\n convert.rgb.keyword = function (rgb) {\n var reversed = reverseKeywords[rgb];\n\n if (reversed) {\n return reversed;\n }\n\n var currentClosestDistance = Infinity;\n var currentClosestKeyword;\n\n for (var keyword in colorName) {\n if (colorName.hasOwnProperty(keyword)) {\n var value = colorName[keyword]; // Compute comparative distance\n\n var distance = comparativeDistance(rgb, value); // Check if its less, if so set as closest\n\n if (distance < currentClosestDistance) {\n currentClosestDistance = distance;\n currentClosestKeyword = keyword;\n }\n }\n }\n\n return currentClosestKeyword;\n };\n\n convert.keyword.rgb = function (keyword) {\n return colorName[keyword];\n };\n\n convert.rgb.xyz = function (rgb) {\n var r = rgb[0] / 255;\n var g = rgb[1] / 255;\n var b = rgb[2] / 255; // assume sRGB\n\n r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;\n g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;\n b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;\n var x = r * 0.4124 + g * 0.3576 + b * 0.1805;\n var y = r * 0.2126 + g * 0.7152 + b * 0.0722;\n var z = r * 0.0193 + g * 0.1192 + b * 0.9505;\n return [x * 100, y * 100, z * 100];\n };\n\n convert.rgb.lab = function (rgb) {\n var xyz = convert.rgb.xyz(rgb);\n var x = xyz[0];\n var y = xyz[1];\n var z = xyz[2];\n var l;\n var a;\n var b;\n x /= 95.047;\n y /= 100;\n z /= 108.883;\n x = x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116;\n y = y > 0.008856 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;\n z = z > 0.008856 ? Math.pow(z, 1 / 3) : 7.787 * z + 16 / 116;\n l = 116 * y - 16;\n a = 500 * (x - y);\n b = 200 * (y - z);\n return [l, a, b];\n };\n\n convert.hsl.rgb = function (hsl) {\n var h = hsl[0] / 360;\n var s = hsl[1] / 100;\n var l = hsl[2] / 100;\n var t1;\n var t2;\n var t3;\n var rgb;\n var val;\n\n if (s === 0) {\n val = l * 255;\n return [val, val, val];\n }\n\n if (l < 0.5) {\n t2 = l * (1 + s);\n } else {\n t2 = l + s - l * s;\n }\n\n t1 = 2 * l - t2;\n rgb = [0, 0, 0];\n\n for (var i = 0; i < 3; i++) {\n t3 = h + 1 / 3 * -(i - 1);\n\n if (t3 < 0) {\n t3++;\n }\n\n if (t3 > 1) {\n t3--;\n }\n\n if (6 * t3 < 1) {\n val = t1 + (t2 - t1) * 6 * t3;\n } else if (2 * t3 < 1) {\n val = t2;\n } else if (3 * t3 < 2) {\n val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;\n } else {\n val = t1;\n }\n\n rgb[i] = val * 255;\n }\n\n return rgb;\n };\n\n convert.hsl.hsv = function (hsl) {\n var h = hsl[0];\n var s = hsl[1] / 100;\n var l = hsl[2] / 100;\n var smin = s;\n var lmin = Math.max(l, 0.01);\n var sv;\n var v;\n l *= 2;\n s *= l <= 1 ? l : 2 - l;\n smin *= lmin <= 1 ? lmin : 2 - lmin;\n v = (l + s) / 2;\n sv = l === 0 ? 2 * smin / (lmin + smin) : 2 * s / (l + s);\n return [h, sv * 100, v * 100];\n };\n\n convert.hsv.rgb = function (hsv) {\n var h = hsv[0] / 60;\n var s = hsv[1] / 100;\n var v = hsv[2] / 100;\n var hi = Math.floor(h) % 6;\n var f = h - Math.floor(h);\n var p = 255 * v * (1 - s);\n var q = 255 * v * (1 - s * f);\n var t = 255 * v * (1 - s * (1 - f));\n v *= 255;\n\n switch (hi) {\n case 0:\n return [v, t, p];\n\n case 1:\n return [q, v, p];\n\n case 2:\n return [p, v, t];\n\n case 3:\n return [p, q, v];\n\n case 4:\n return [t, p, v];\n\n case 5:\n return [v, p, q];\n }\n };\n\n convert.hsv.hsl = function (hsv) {\n var h = hsv[0];\n var s = hsv[1] / 100;\n var v = hsv[2] / 100;\n var vmin = Math.max(v, 0.01);\n var lmin;\n var sl;\n var l;\n l = (2 - s) * v;\n lmin = (2 - s) * vmin;\n sl = s * vmin;\n sl /= lmin <= 1 ? lmin : 2 - lmin;\n sl = sl || 0;\n l /= 2;\n return [h, sl * 100, l * 100];\n }; // http://dev.w3.org/csswg/css-color/#hwb-to-rgb\n\n\n convert.hwb.rgb = function (hwb) {\n var h = hwb[0] / 360;\n var wh = hwb[1] / 100;\n var bl = hwb[2] / 100;\n var ratio = wh + bl;\n var i;\n var v;\n var f;\n var n; // wh + bl cant be > 1\n\n if (ratio > 1) {\n wh /= ratio;\n bl /= ratio;\n }\n\n i = Math.floor(6 * h);\n v = 1 - bl;\n f = 6 * h - i;\n\n if ((i & 0x01) !== 0) {\n f = 1 - f;\n }\n\n n = wh + f * (v - wh); // linear interpolation\n\n var r;\n var g;\n var b;\n\n switch (i) {\n default:\n case 6:\n case 0:\n r = v;\n g = n;\n b = wh;\n break;\n\n case 1:\n r = n;\n g = v;\n b = wh;\n break;\n\n case 2:\n r = wh;\n g = v;\n b = n;\n break;\n\n case 3:\n r = wh;\n g = n;\n b = v;\n break;\n\n case 4:\n r = n;\n g = wh;\n b = v;\n break;\n\n case 5:\n r = v;\n g = wh;\n b = n;\n break;\n }\n\n return [r * 255, g * 255, b * 255];\n };\n\n convert.cmyk.rgb = function (cmyk) {\n var c = cmyk[0] / 100;\n var m = cmyk[1] / 100;\n var y = cmyk[2] / 100;\n var k = cmyk[3] / 100;\n var r;\n var g;\n var b;\n r = 1 - Math.min(1, c * (1 - k) + k);\n g = 1 - Math.min(1, m * (1 - k) + k);\n b = 1 - Math.min(1, y * (1 - k) + k);\n return [r * 255, g * 255, b * 255];\n };\n\n convert.xyz.rgb = function (xyz) {\n var x = xyz[0] / 100;\n var y = xyz[1] / 100;\n var z = xyz[2] / 100;\n var r;\n var g;\n var b;\n r = x * 3.2406 + y * -1.5372 + z * -0.4986;\n g = x * -0.9689 + y * 1.8758 + z * 0.0415;\n b = x * 0.0557 + y * -0.2040 + z * 1.0570; // assume sRGB\n\n r = r > 0.0031308 ? 1.055 * Math.pow(r, 1.0 / 2.4) - 0.055 : r * 12.92;\n g = g > 0.0031308 ? 1.055 * Math.pow(g, 1.0 / 2.4) - 0.055 : g * 12.92;\n b = b > 0.0031308 ? 1.055 * Math.pow(b, 1.0 / 2.4) - 0.055 : b * 12.92;\n r = Math.min(Math.max(0, r), 1);\n g = Math.min(Math.max(0, g), 1);\n b = Math.min(Math.max(0, b), 1);\n return [r * 255, g * 255, b * 255];\n };\n\n convert.xyz.lab = function (xyz) {\n var x = xyz[0];\n var y = xyz[1];\n var z = xyz[2];\n var l;\n var a;\n var b;\n x /= 95.047;\n y /= 100;\n z /= 108.883;\n x = x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116;\n y = y > 0.008856 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;\n z = z > 0.008856 ? Math.pow(z, 1 / 3) : 7.787 * z + 16 / 116;\n l = 116 * y - 16;\n a = 500 * (x - y);\n b = 200 * (y - z);\n return [l, a, b];\n };\n\n convert.lab.xyz = function (lab) {\n var l = lab[0];\n var a = lab[1];\n var b = lab[2];\n var x;\n var y;\n var z;\n y = (l + 16) / 116;\n x = a / 500 + y;\n z = y - b / 200;\n var y2 = Math.pow(y, 3);\n var x2 = Math.pow(x, 3);\n var z2 = Math.pow(z, 3);\n y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787;\n x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787;\n z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787;\n x *= 95.047;\n y *= 100;\n z *= 108.883;\n return [x, y, z];\n };\n\n convert.lab.lch = function (lab) {\n var l = lab[0];\n var a = lab[1];\n var b = lab[2];\n var hr;\n var h;\n var c;\n hr = Math.atan2(b, a);\n h = hr * 360 / 2 / Math.PI;\n\n if (h < 0) {\n h += 360;\n }\n\n c = Math.sqrt(a * a + b * b);\n return [l, c, h];\n };\n\n convert.lch.lab = function (lch) {\n var l = lch[0];\n var c = lch[1];\n var h = lch[2];\n var a;\n var b;\n var hr;\n hr = h / 360 * 2 * Math.PI;\n a = c * Math.cos(hr);\n b = c * Math.sin(hr);\n return [l, a, b];\n };\n\n convert.rgb.ansi16 = function (args) {\n var r = args[0];\n var g = args[1];\n var b = args[2];\n var value = 1 in arguments ? arguments[1] : convert.rgb.hsv(args)[2]; // hsv -> ansi16 optimization\n\n value = Math.round(value / 50);\n\n if (value === 0) {\n return 30;\n }\n\n var ansi = 30 + (Math.round(b / 255) << 2 | Math.round(g / 255) << 1 | Math.round(r / 255));\n\n if (value === 2) {\n ansi += 60;\n }\n\n return ansi;\n };\n\n convert.hsv.ansi16 = function (args) {\n // optimization here; we already know the value and don't need to get\n // it converted for us.\n return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]);\n };\n\n convert.rgb.ansi256 = function (args) {\n var r = args[0];\n var g = args[1];\n var b = args[2]; // we use the extended greyscale palette here, with the exception of\n // black and white. normal palette only has 4 greyscale shades.\n\n if (r === g && g === b) {\n if (r < 8) {\n return 16;\n }\n\n if (r > 248) {\n return 231;\n }\n\n return Math.round((r - 8) / 247 * 24) + 232;\n }\n\n var ansi = 16 + 36 * Math.round(r / 255 * 5) + 6 * Math.round(g / 255 * 5) + Math.round(b / 255 * 5);\n return ansi;\n };\n\n convert.ansi16.rgb = function (args) {\n var color = args % 10; // handle greyscale\n\n if (color === 0 || color === 7) {\n if (args > 50) {\n color += 3.5;\n }\n\n color = color / 10.5 * 255;\n return [color, color, color];\n }\n\n var mult = (~~(args > 50) + 1) * 0.5;\n var r = (color & 1) * mult * 255;\n var g = (color >> 1 & 1) * mult * 255;\n var b = (color >> 2 & 1) * mult * 255;\n return [r, g, b];\n };\n\n convert.ansi256.rgb = function (args) {\n // handle greyscale\n if (args >= 232) {\n var c = (args - 232) * 10 + 8;\n return [c, c, c];\n }\n\n args -= 16;\n var rem;\n var r = Math.floor(args / 36) / 5 * 255;\n var g = Math.floor((rem = args % 36) / 6) / 5 * 255;\n var b = rem % 6 / 5 * 255;\n return [r, g, b];\n };\n\n convert.rgb.hex = function (args) {\n var integer = ((Math.round(args[0]) & 0xFF) << 16) + ((Math.round(args[1]) & 0xFF) << 8) + (Math.round(args[2]) & 0xFF);\n var string = integer.toString(16).toUpperCase();\n return '000000'.substring(string.length) + string;\n };\n\n convert.hex.rgb = function (args) {\n var match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);\n\n if (!match) {\n return [0, 0, 0];\n }\n\n var colorString = match[0];\n\n if (match[0].length === 3) {\n colorString = colorString.split('').map(function (char) {\n return char + char;\n }).join('');\n }\n\n var integer = parseInt(colorString, 16);\n var r = integer >> 16 & 0xFF;\n var g = integer >> 8 & 0xFF;\n var b = integer & 0xFF;\n return [r, g, b];\n };\n\n convert.rgb.hcg = function (rgb) {\n var r = rgb[0] / 255;\n var g = rgb[1] / 255;\n var b = rgb[2] / 255;\n var max = Math.max(Math.max(r, g), b);\n var min = Math.min(Math.min(r, g), b);\n var chroma = max - min;\n var grayscale;\n var hue;\n\n if (chroma < 1) {\n grayscale = min / (1 - chroma);\n } else {\n grayscale = 0;\n }\n\n if (chroma <= 0) {\n hue = 0;\n } else if (max === r) {\n hue = (g - b) / chroma % 6;\n } else if (max === g) {\n hue = 2 + (b - r) / chroma;\n } else {\n hue = 4 + (r - g) / chroma + 4;\n }\n\n hue /= 6;\n hue %= 1;\n return [hue * 360, chroma * 100, grayscale * 100];\n };\n\n convert.hsl.hcg = function (hsl) {\n var s = hsl[1] / 100;\n var l = hsl[2] / 100;\n var c = 1;\n var f = 0;\n\n if (l < 0.5) {\n c = 2.0 * s * l;\n } else {\n c = 2.0 * s * (1.0 - l);\n }\n\n if (c < 1.0) {\n f = (l - 0.5 * c) / (1.0 - c);\n }\n\n return [hsl[0], c * 100, f * 100];\n };\n\n convert.hsv.hcg = function (hsv) {\n var s = hsv[1] / 100;\n var v = hsv[2] / 100;\n var c = s * v;\n var f = 0;\n\n if (c < 1.0) {\n f = (v - c) / (1 - c);\n }\n\n return [hsv[0], c * 100, f * 100];\n };\n\n convert.hcg.rgb = function (hcg) {\n var h = hcg[0] / 360;\n var c = hcg[1] / 100;\n var g = hcg[2] / 100;\n\n if (c === 0.0) {\n return [g * 255, g * 255, g * 255];\n }\n\n var pure = [0, 0, 0];\n var hi = h % 1 * 6;\n var v = hi % 1;\n var w = 1 - v;\n var mg = 0;\n\n switch (Math.floor(hi)) {\n case 0:\n pure[0] = 1;\n pure[1] = v;\n pure[2] = 0;\n break;\n\n case 1:\n pure[0] = w;\n pure[1] = 1;\n pure[2] = 0;\n break;\n\n case 2:\n pure[0] = 0;\n pure[1] = 1;\n pure[2] = v;\n break;\n\n case 3:\n pure[0] = 0;\n pure[1] = w;\n pure[2] = 1;\n break;\n\n case 4:\n pure[0] = v;\n pure[1] = 0;\n pure[2] = 1;\n break;\n\n default:\n pure[0] = 1;\n pure[1] = 0;\n pure[2] = w;\n }\n\n mg = (1.0 - c) * g;\n return [(c * pure[0] + mg) * 255, (c * pure[1] + mg) * 255, (c * pure[2] + mg) * 255];\n };\n\n convert.hcg.hsv = function (hcg) {\n var c = hcg[1] / 100;\n var g = hcg[2] / 100;\n var v = c + g * (1.0 - c);\n var f = 0;\n\n if (v > 0.0) {\n f = c / v;\n }\n\n return [hcg[0], f * 100, v * 100];\n };\n\n convert.hcg.hsl = function (hcg) {\n var c = hcg[1] / 100;\n var g = hcg[2] / 100;\n var l = g * (1.0 - c) + 0.5 * c;\n var s = 0;\n\n if (l > 0.0 && l < 0.5) {\n s = c / (2 * l);\n } else if (l >= 0.5 && l < 1.0) {\n s = c / (2 * (1 - l));\n }\n\n return [hcg[0], s * 100, l * 100];\n };\n\n convert.hcg.hwb = function (hcg) {\n var c = hcg[1] / 100;\n var g = hcg[2] / 100;\n var v = c + g * (1.0 - c);\n return [hcg[0], (v - c) * 100, (1 - v) * 100];\n };\n\n convert.hwb.hcg = function (hwb) {\n var w = hwb[1] / 100;\n var b = hwb[2] / 100;\n var v = 1 - b;\n var c = v - w;\n var g = 0;\n\n if (c < 1) {\n g = (v - c) / (1 - c);\n }\n\n return [hwb[0], c * 100, g * 100];\n };\n\n convert.apple.rgb = function (apple) {\n return [apple[0] / 65535 * 255, apple[1] / 65535 * 255, apple[2] / 65535 * 255];\n };\n\n convert.rgb.apple = function (rgb) {\n return [rgb[0] / 255 * 65535, rgb[1] / 255 * 65535, rgb[2] / 255 * 65535];\n };\n\n convert.gray.rgb = function (args) {\n return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255];\n };\n\n convert.gray.hsl = convert.gray.hsv = function (args) {\n return [0, 0, args[0]];\n };\n\n convert.gray.hwb = function (gray) {\n return [0, 100, gray[0]];\n };\n\n convert.gray.cmyk = function (gray) {\n return [0, 0, 0, gray[0]];\n };\n\n convert.gray.lab = function (gray) {\n return [gray[0], 0, 0];\n };\n\n convert.gray.hex = function (gray) {\n var val = Math.round(gray[0] / 100 * 255) & 0xFF;\n var integer = (val << 16) + (val << 8) + val;\n var string = integer.toString(16).toUpperCase();\n return '000000'.substring(string.length) + string;\n };\n\n convert.rgb.gray = function (rgb) {\n var val = (rgb[0] + rgb[1] + rgb[2]) / 3;\n return [val / 255 * 100];\n };\n });\n var conversions_1 = conversions.rgb;\n var conversions_2 = conversions.hsl;\n var conversions_3 = conversions.hsv;\n var conversions_4 = conversions.hwb;\n var conversions_5 = conversions.cmyk;\n var conversions_6 = conversions.xyz;\n var conversions_7 = conversions.lab;\n var conversions_8 = conversions.lch;\n var conversions_9 = conversions.hex;\n var conversions_10 = conversions.keyword;\n var conversions_11 = conversions.ansi16;\n var conversions_12 = conversions.ansi256;\n var conversions_13 = conversions.hcg;\n var conversions_14 = conversions.apple;\n var conversions_15 = conversions.gray;\n /*\n \tthis function routes a model to all other models.\n \n \tall functions that are routed have a property `.conversion` attached\n \tto the returned synthetic function. This property is an array\n \tof strings, each with the steps in between the 'from' and 'to'\n \tcolor models (inclusive).\n \n \tconversions that are not possible simply are not included.\n */\n\n function buildGraph() {\n var graph = {}; // https://jsperf.com/object-keys-vs-for-in-with-closure/3\n\n var models = Object.keys(conversions);\n\n for (var len = models.length, i = 0; i < len; i++) {\n graph[models[i]] = {\n // http://jsperf.com/1-vs-infinity\n // micro-opt, but this is simple.\n distance: -1,\n parent: null\n };\n }\n\n return graph;\n } // https://en.wikipedia.org/wiki/Breadth-first_search\n\n\n function deriveBFS(fromModel) {\n var graph = buildGraph();\n var queue = [fromModel]; // unshift -> queue -> pop\n\n graph[fromModel].distance = 0;\n\n while (queue.length) {\n var current = queue.pop();\n var adjacents = Object.keys(conversions[current]);\n\n for (var len = adjacents.length, i = 0; i < len; i++) {\n var adjacent = adjacents[i];\n var node = graph[adjacent];\n\n if (node.distance === -1) {\n node.distance = graph[current].distance + 1;\n node.parent = current;\n queue.unshift(adjacent);\n }\n }\n }\n\n return graph;\n }\n\n function link(from, to) {\n return function (args) {\n return to(from(args));\n };\n }\n\n function wrapConversion(toModel, graph) {\n var path = [graph[toModel].parent, toModel];\n var fn = conversions[graph[toModel].parent][toModel];\n var cur = graph[toModel].parent;\n\n while (graph[cur].parent) {\n path.unshift(graph[cur].parent);\n fn = link(conversions[graph[cur].parent][cur], fn);\n cur = graph[cur].parent;\n }\n\n fn.conversion = path;\n return fn;\n }\n\n var route = function (fromModel) {\n var graph = deriveBFS(fromModel);\n var conversion = {};\n var models = Object.keys(graph);\n\n for (var len = models.length, i = 0; i < len; i++) {\n var toModel = models[i];\n var node = graph[toModel];\n\n if (node.parent === null) {\n // no possible conversion, or this node is the source model.\n continue;\n }\n\n conversion[toModel] = wrapConversion(toModel, graph);\n }\n\n return conversion;\n };\n\n var convert = {};\n var models = Object.keys(conversions);\n\n function wrapRaw(fn) {\n var wrappedFn = function (args) {\n if (args === undefined || args === null) {\n return args;\n }\n\n if (arguments.length > 1) {\n args = Array.prototype.slice.call(arguments);\n }\n\n return fn(args);\n }; // preserve .conversion property if there is one\n\n\n if ('conversion' in fn) {\n wrappedFn.conversion = fn.conversion;\n }\n\n return wrappedFn;\n }\n\n function wrapRounded(fn) {\n var wrappedFn = function (args) {\n if (args === undefined || args === null) {\n return args;\n }\n\n if (arguments.length > 1) {\n args = Array.prototype.slice.call(arguments);\n }\n\n var result = fn(args); // we're assuming the result is an array here.\n // see notice in conversions.js; don't use box types\n // in conversion functions.\n\n if (typeof result === 'object') {\n for (var len = result.length, i = 0; i < len; i++) {\n result[i] = Math.round(result[i]);\n }\n }\n\n return result;\n }; // preserve .conversion property if there is one\n\n\n if ('conversion' in fn) {\n wrappedFn.conversion = fn.conversion;\n }\n\n return wrappedFn;\n }\n\n models.forEach(function (fromModel) {\n convert[fromModel] = {};\n Object.defineProperty(convert[fromModel], 'channels', {\n value: conversions[fromModel].channels\n });\n Object.defineProperty(convert[fromModel], 'labels', {\n value: conversions[fromModel].labels\n });\n var routes = route(fromModel);\n var routeModels = Object.keys(routes);\n routeModels.forEach(function (toModel) {\n var fn = routes[toModel];\n convert[fromModel][toModel] = wrapRounded(fn);\n convert[fromModel][toModel].raw = wrapRaw(fn);\n });\n });\n var colorConvert = convert;\n var colorName$1 = {\n \"aliceblue\": [240, 248, 255],\n \"antiquewhite\": [250, 235, 215],\n \"aqua\": [0, 255, 255],\n \"aquamarine\": [127, 255, 212],\n \"azure\": [240, 255, 255],\n \"beige\": [245, 245, 220],\n \"bisque\": [255, 228, 196],\n \"black\": [0, 0, 0],\n \"blanchedalmond\": [255, 235, 205],\n \"blue\": [0, 0, 255],\n \"blueviolet\": [138, 43, 226],\n \"brown\": [165, 42, 42],\n \"burlywood\": [222, 184, 135],\n \"cadetblue\": [95, 158, 160],\n \"chartreuse\": [127, 255, 0],\n \"chocolate\": [210, 105, 30],\n \"coral\": [255, 127, 80],\n \"cornflowerblue\": [100, 149, 237],\n \"cornsilk\": [255, 248, 220],\n \"crimson\": [220, 20, 60],\n \"cyan\": [0, 255, 255],\n \"darkblue\": [0, 0, 139],\n \"darkcyan\": [0, 139, 139],\n \"darkgoldenrod\": [184, 134, 11],\n \"darkgray\": [169, 169, 169],\n \"darkgreen\": [0, 100, 0],\n \"darkgrey\": [169, 169, 169],\n \"darkkhaki\": [189, 183, 107],\n \"darkmagenta\": [139, 0, 139],\n \"darkolivegreen\": [85, 107, 47],\n \"darkorange\": [255, 140, 0],\n \"darkorchid\": [153, 50, 204],\n \"darkred\": [139, 0, 0],\n \"darksalmon\": [233, 150, 122],\n \"darkseagreen\": [143, 188, 143],\n \"darkslateblue\": [72, 61, 139],\n \"darkslategray\": [47, 79, 79],\n \"darkslategrey\": [47, 79, 79],\n \"darkturquoise\": [0, 206, 209],\n \"darkviolet\": [148, 0, 211],\n \"deeppink\": [255, 20, 147],\n \"deepskyblue\": [0, 191, 255],\n \"dimgray\": [105, 105, 105],\n \"dimgrey\": [105, 105, 105],\n \"dodgerblue\": [30, 144, 255],\n \"firebrick\": [178, 34, 34],\n \"floralwhite\": [255, 250, 240],\n \"forestgreen\": [34, 139, 34],\n \"fuchsia\": [255, 0, 255],\n \"gainsboro\": [220, 220, 220],\n \"ghostwhite\": [248, 248, 255],\n \"gold\": [255, 215, 0],\n \"goldenrod\": [218, 165, 32],\n \"gray\": [128, 128, 128],\n \"green\": [0, 128, 0],\n \"greenyellow\": [173, 255, 47],\n \"grey\": [128, 128, 128],\n \"honeydew\": [240, 255, 240],\n \"hotpink\": [255, 105, 180],\n \"indianred\": [205, 92, 92],\n \"indigo\": [75, 0, 130],\n \"ivory\": [255, 255, 240],\n \"khaki\": [240, 230, 140],\n \"lavender\": [230, 230, 250],\n \"lavenderblush\": [255, 240, 245],\n \"lawngreen\": [124, 252, 0],\n \"lemonchiffon\": [255, 250, 205],\n \"lightblue\": [173, 216, 230],\n \"lightcoral\": [240, 128, 128],\n \"lightcyan\": [224, 255, 255],\n \"lightgoldenrodyellow\": [250, 250, 210],\n \"lightgray\": [211, 211, 211],\n \"lightgreen\": [144, 238, 144],\n \"lightgrey\": [211, 211, 211],\n \"lightpink\": [255, 182, 193],\n \"lightsalmon\": [255, 160, 122],\n \"lightseagreen\": [32, 178, 170],\n \"lightskyblue\": [135, 206, 250],\n \"lightslategray\": [119, 136, 153],\n \"lightslategrey\": [119, 136, 153],\n \"lightsteelblue\": [176, 196, 222],\n \"lightyellow\": [255, 255, 224],\n \"lime\": [0, 255, 0],\n \"limegreen\": [50, 205, 50],\n \"linen\": [250, 240, 230],\n \"magenta\": [255, 0, 255],\n \"maroon\": [128, 0, 0],\n \"mediumaquamarine\": [102, 205, 170],\n \"mediumblue\": [0, 0, 205],\n \"mediumorchid\": [186, 85, 211],\n \"mediumpurple\": [147, 112, 219],\n \"mediumseagreen\": [60, 179, 113],\n \"mediumslateblue\": [123, 104, 238],\n \"mediumspringgreen\": [0, 250, 154],\n \"mediumturquoise\": [72, 209, 204],\n \"mediumvioletred\": [199, 21, 133],\n \"midnightblue\": [25, 25, 112],\n \"mintcream\": [245, 255, 250],\n \"mistyrose\": [255, 228, 225],\n \"moccasin\": [255, 228, 181],\n \"navajowhite\": [255, 222, 173],\n \"navy\": [0, 0, 128],\n \"oldlace\": [253, 245, 230],\n \"olive\": [128, 128, 0],\n \"olivedrab\": [107, 142, 35],\n \"orange\": [255, 165, 0],\n \"orangered\": [255, 69, 0],\n \"orchid\": [218, 112, 214],\n \"palegoldenrod\": [238, 232, 170],\n \"palegreen\": [152, 251, 152],\n \"paleturquoise\": [175, 238, 238],\n \"palevioletred\": [219, 112, 147],\n \"papayawhip\": [255, 239, 213],\n \"peachpuff\": [255, 218, 185],\n \"peru\": [205, 133, 63],\n \"pink\": [255, 192, 203],\n \"plum\": [221, 160, 221],\n \"powderblue\": [176, 224, 230],\n \"purple\": [128, 0, 128],\n \"rebeccapurple\": [102, 51, 153],\n \"red\": [255, 0, 0],\n \"rosybrown\": [188, 143, 143],\n \"royalblue\": [65, 105, 225],\n \"saddlebrown\": [139, 69, 19],\n \"salmon\": [250, 128, 114],\n \"sandybrown\": [244, 164, 96],\n \"seagreen\": [46, 139, 87],\n \"seashell\": [255, 245, 238],\n \"sienna\": [160, 82, 45],\n \"silver\": [192, 192, 192],\n \"skyblue\": [135, 206, 235],\n \"slateblue\": [106, 90, 205],\n \"slategray\": [112, 128, 144],\n \"slategrey\": [112, 128, 144],\n \"snow\": [255, 250, 250],\n \"springgreen\": [0, 255, 127],\n \"steelblue\": [70, 130, 180],\n \"tan\": [210, 180, 140],\n \"teal\": [0, 128, 128],\n \"thistle\": [216, 191, 216],\n \"tomato\": [255, 99, 71],\n \"turquoise\": [64, 224, 208],\n \"violet\": [238, 130, 238],\n \"wheat\": [245, 222, 179],\n \"white\": [255, 255, 255],\n \"whitesmoke\": [245, 245, 245],\n \"yellow\": [255, 255, 0],\n \"yellowgreen\": [154, 205, 50]\n };\n /* MIT license */\n\n var colorString = {\n getRgba: getRgba,\n getHsla: getHsla,\n getRgb: getRgb,\n getHsl: getHsl,\n getHwb: getHwb,\n getAlpha: getAlpha,\n hexString: hexString,\n rgbString: rgbString,\n rgbaString: rgbaString,\n percentString: percentString,\n percentaString: percentaString,\n hslString: hslString,\n hslaString: hslaString,\n hwbString: hwbString,\n keyword: keyword\n };\n\n function getRgba(string) {\n if (!string) {\n return;\n }\n\n var abbr = /^#([a-fA-F0-9]{3,4})$/i,\n hex = /^#([a-fA-F0-9]{6}([a-fA-F0-9]{2})?)$/i,\n rgba = /^rgba?\\(\\s*([+-]?\\d+)\\s*,\\s*([+-]?\\d+)\\s*,\\s*([+-]?\\d+)\\s*(?:,\\s*([+-]?[\\d\\.]+)\\s*)?\\)$/i,\n per = /^rgba?\\(\\s*([+-]?[\\d\\.]+)\\%\\s*,\\s*([+-]?[\\d\\.]+)\\%\\s*,\\s*([+-]?[\\d\\.]+)\\%\\s*(?:,\\s*([+-]?[\\d\\.]+)\\s*)?\\)$/i,\n keyword = /(\\w+)/;\n var rgb = [0, 0, 0],\n a = 1,\n match = string.match(abbr),\n hexAlpha = \"\";\n\n if (match) {\n match = match[1];\n hexAlpha = match[3];\n\n for (var i = 0; i < rgb.length; i++) {\n rgb[i] = parseInt(match[i] + match[i], 16);\n }\n\n if (hexAlpha) {\n a = Math.round(parseInt(hexAlpha + hexAlpha, 16) / 255 * 100) / 100;\n }\n } else if (match = string.match(hex)) {\n hexAlpha = match[2];\n match = match[1];\n\n for (var i = 0; i < rgb.length; i++) {\n rgb[i] = parseInt(match.slice(i * 2, i * 2 + 2), 16);\n }\n\n if (hexAlpha) {\n a = Math.round(parseInt(hexAlpha, 16) / 255 * 100) / 100;\n }\n } else if (match = string.match(rgba)) {\n for (var i = 0; i < rgb.length; i++) {\n rgb[i] = parseInt(match[i + 1]);\n }\n\n a = parseFloat(match[4]);\n } else if (match = string.match(per)) {\n for (var i = 0; i < rgb.length; i++) {\n rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55);\n }\n\n a = parseFloat(match[4]);\n } else if (match = string.match(keyword)) {\n if (match[1] == \"transparent\") {\n return [0, 0, 0, 0];\n }\n\n rgb = colorName$1[match[1]];\n\n if (!rgb) {\n return;\n }\n }\n\n for (var i = 0; i < rgb.length; i++) {\n rgb[i] = scale(rgb[i], 0, 255);\n }\n\n if (!a && a != 0) {\n a = 1;\n } else {\n a = scale(a, 0, 1);\n }\n\n rgb[3] = a;\n return rgb;\n }\n\n function getHsla(string) {\n if (!string) {\n return;\n }\n\n var hsl = /^hsla?\\(\\s*([+-]?\\d+)(?:deg)?\\s*,\\s*([+-]?[\\d\\.]+)%\\s*,\\s*([+-]?[\\d\\.]+)%\\s*(?:,\\s*([+-]?[\\d\\.]+)\\s*)?\\)/;\n var match = string.match(hsl);\n\n if (match) {\n var alpha = parseFloat(match[4]);\n var h = scale(parseInt(match[1]), 0, 360),\n s = scale(parseFloat(match[2]), 0, 100),\n l = scale(parseFloat(match[3]), 0, 100),\n a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);\n return [h, s, l, a];\n }\n }\n\n function getHwb(string) {\n if (!string) {\n return;\n }\n\n var hwb = /^hwb\\(\\s*([+-]?\\d+)(?:deg)?\\s*,\\s*([+-]?[\\d\\.]+)%\\s*,\\s*([+-]?[\\d\\.]+)%\\s*(?:,\\s*([+-]?[\\d\\.]+)\\s*)?\\)/;\n var match = string.match(hwb);\n\n if (match) {\n var alpha = parseFloat(match[4]);\n var h = scale(parseInt(match[1]), 0, 360),\n w = scale(parseFloat(match[2]), 0, 100),\n b = scale(parseFloat(match[3]), 0, 100),\n a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);\n return [h, w, b, a];\n }\n }\n\n function getRgb(string) {\n var rgba = getRgba(string);\n return rgba && rgba.slice(0, 3);\n }\n\n function getHsl(string) {\n var hsla = getHsla(string);\n return hsla && hsla.slice(0, 3);\n }\n\n function getAlpha(string) {\n var vals = getRgba(string);\n\n if (vals) {\n return vals[3];\n } else if (vals = getHsla(string)) {\n return vals[3];\n } else if (vals = getHwb(string)) {\n return vals[3];\n }\n } // generators\n\n\n function hexString(rgba, a) {\n var a = a !== undefined && rgba.length === 3 ? a : rgba[3];\n return \"#\" + hexDouble(rgba[0]) + hexDouble(rgba[1]) + hexDouble(rgba[2]) + (a >= 0 && a < 1 ? hexDouble(Math.round(a * 255)) : \"\");\n }\n\n function rgbString(rgba, alpha) {\n if (alpha < 1 || rgba[3] && rgba[3] < 1) {\n return rgbaString(rgba, alpha);\n }\n\n return \"rgb(\" + rgba[0] + \", \" + rgba[1] + \", \" + rgba[2] + \")\";\n }\n\n function rgbaString(rgba, alpha) {\n if (alpha === undefined) {\n alpha = rgba[3] !== undefined ? rgba[3] : 1;\n }\n\n return \"rgba(\" + rgba[0] + \", \" + rgba[1] + \", \" + rgba[2] + \", \" + alpha + \")\";\n }\n\n function percentString(rgba, alpha) {\n if (alpha < 1 || rgba[3] && rgba[3] < 1) {\n return percentaString(rgba, alpha);\n }\n\n var r = Math.round(rgba[0] / 255 * 100),\n g = Math.round(rgba[1] / 255 * 100),\n b = Math.round(rgba[2] / 255 * 100);\n return \"rgb(\" + r + \"%, \" + g + \"%, \" + b + \"%)\";\n }\n\n function percentaString(rgba, alpha) {\n var r = Math.round(rgba[0] / 255 * 100),\n g = Math.round(rgba[1] / 255 * 100),\n b = Math.round(rgba[2] / 255 * 100);\n return \"rgba(\" + r + \"%, \" + g + \"%, \" + b + \"%, \" + (alpha || rgba[3] || 1) + \")\";\n }\n\n function hslString(hsla, alpha) {\n if (alpha < 1 || hsla[3] && hsla[3] < 1) {\n return hslaString(hsla, alpha);\n }\n\n return \"hsl(\" + hsla[0] + \", \" + hsla[1] + \"%, \" + hsla[2] + \"%)\";\n }\n\n function hslaString(hsla, alpha) {\n if (alpha === undefined) {\n alpha = hsla[3] !== undefined ? hsla[3] : 1;\n }\n\n return \"hsla(\" + hsla[0] + \", \" + hsla[1] + \"%, \" + hsla[2] + \"%, \" + alpha + \")\";\n } // hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax\n // (hwb have alpha optional & 1 is default value)\n\n\n function hwbString(hwb, alpha) {\n if (alpha === undefined) {\n alpha = hwb[3] !== undefined ? hwb[3] : 1;\n }\n\n return \"hwb(\" + hwb[0] + \", \" + hwb[1] + \"%, \" + hwb[2] + \"%\" + (alpha !== undefined && alpha !== 1 ? \", \" + alpha : \"\") + \")\";\n }\n\n function keyword(rgb) {\n return reverseNames[rgb.slice(0, 3)];\n } // helpers\n\n\n function scale(num, min, max) {\n return Math.min(Math.max(min, num), max);\n }\n\n function hexDouble(num) {\n var str = num.toString(16).toUpperCase();\n return str.length < 2 ? \"0\" + str : str;\n } //create a list of reverse color names\n\n\n var reverseNames = {};\n\n for (var name in colorName$1) {\n reverseNames[colorName$1[name]] = name;\n }\n /* MIT license */\n\n\n var Color = function (obj) {\n if (obj instanceof Color) {\n return obj;\n }\n\n if (!(this instanceof Color)) {\n return new Color(obj);\n }\n\n this.valid = false;\n this.values = {\n rgb: [0, 0, 0],\n hsl: [0, 0, 0],\n hsv: [0, 0, 0],\n hwb: [0, 0, 0],\n cmyk: [0, 0, 0, 0],\n alpha: 1\n }; // parse Color() argument\n\n var vals;\n\n if (typeof obj === 'string') {\n vals = colorString.getRgba(obj);\n\n if (vals) {\n this.setValues('rgb', vals);\n } else if (vals = colorString.getHsla(obj)) {\n this.setValues('hsl', vals);\n } else if (vals = colorString.getHwb(obj)) {\n this.setValues('hwb', vals);\n }\n } else if (typeof obj === 'object') {\n vals = obj;\n\n if (vals.r !== undefined || vals.red !== undefined) {\n this.setValues('rgb', vals);\n } else if (vals.l !== undefined || vals.lightness !== undefined) {\n this.setValues('hsl', vals);\n } else if (vals.v !== undefined || vals.value !== undefined) {\n this.setValues('hsv', vals);\n } else if (vals.w !== undefined || vals.whiteness !== undefined) {\n this.setValues('hwb', vals);\n } else if (vals.c !== undefined || vals.cyan !== undefined) {\n this.setValues('cmyk', vals);\n }\n }\n };\n\n Color.prototype = {\n isValid: function () {\n return this.valid;\n },\n rgb: function () {\n return this.setSpace('rgb', arguments);\n },\n hsl: function () {\n return this.setSpace('hsl', arguments);\n },\n hsv: function () {\n return this.setSpace('hsv', arguments);\n },\n hwb: function () {\n return this.setSpace('hwb', arguments);\n },\n cmyk: function () {\n return this.setSpace('cmyk', arguments);\n },\n rgbArray: function () {\n return this.values.rgb;\n },\n hslArray: function () {\n return this.values.hsl;\n },\n hsvArray: function () {\n return this.values.hsv;\n },\n hwbArray: function () {\n var values = this.values;\n\n if (values.alpha !== 1) {\n return values.hwb.concat([values.alpha]);\n }\n\n return values.hwb;\n },\n cmykArray: function () {\n return this.values.cmyk;\n },\n rgbaArray: function () {\n var values = this.values;\n return values.rgb.concat([values.alpha]);\n },\n hslaArray: function () {\n var values = this.values;\n return values.hsl.concat([values.alpha]);\n },\n alpha: function (val) {\n if (val === undefined) {\n return this.values.alpha;\n }\n\n this.setValues('alpha', val);\n return this;\n },\n red: function (val) {\n return this.setChannel('rgb', 0, val);\n },\n green: function (val) {\n return this.setChannel('rgb', 1, val);\n },\n blue: function (val) {\n return this.setChannel('rgb', 2, val);\n },\n hue: function (val) {\n if (val) {\n val %= 360;\n val = val < 0 ? 360 + val : val;\n }\n\n return this.setChannel('hsl', 0, val);\n },\n saturation: function (val) {\n return this.setChannel('hsl', 1, val);\n },\n lightness: function (val) {\n return this.setChannel('hsl', 2, val);\n },\n saturationv: function (val) {\n return this.setChannel('hsv', 1, val);\n },\n whiteness: function (val) {\n return this.setChannel('hwb', 1, val);\n },\n blackness: function (val) {\n return this.setChannel('hwb', 2, val);\n },\n value: function (val) {\n return this.setChannel('hsv', 2, val);\n },\n cyan: function (val) {\n return this.setChannel('cmyk', 0, val);\n },\n magenta: function (val) {\n return this.setChannel('cmyk', 1, val);\n },\n yellow: function (val) {\n return this.setChannel('cmyk', 2, val);\n },\n black: function (val) {\n return this.setChannel('cmyk', 3, val);\n },\n hexString: function () {\n return colorString.hexString(this.values.rgb);\n },\n rgbString: function () {\n return colorString.rgbString(this.values.rgb, this.values.alpha);\n },\n rgbaString: function () {\n return colorString.rgbaString(this.values.rgb, this.values.alpha);\n },\n percentString: function () {\n return colorString.percentString(this.values.rgb, this.values.alpha);\n },\n hslString: function () {\n return colorString.hslString(this.values.hsl, this.values.alpha);\n },\n hslaString: function () {\n return colorString.hslaString(this.values.hsl, this.values.alpha);\n },\n hwbString: function () {\n return colorString.hwbString(this.values.hwb, this.values.alpha);\n },\n keyword: function () {\n return colorString.keyword(this.values.rgb, this.values.alpha);\n },\n rgbNumber: function () {\n var rgb = this.values.rgb;\n return rgb[0] << 16 | rgb[1] << 8 | rgb[2];\n },\n luminosity: function () {\n // http://www.w3.org/TR/WCAG20/#relativeluminancedef\n var rgb = this.values.rgb;\n var lum = [];\n\n for (var i = 0; i < rgb.length; i++) {\n var chan = rgb[i] / 255;\n lum[i] = chan <= 0.03928 ? chan / 12.92 : Math.pow((chan + 0.055) / 1.055, 2.4);\n }\n\n return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2];\n },\n contrast: function (color2) {\n // http://www.w3.org/TR/WCAG20/#contrast-ratiodef\n var lum1 = this.luminosity();\n var lum2 = color2.luminosity();\n\n if (lum1 > lum2) {\n return (lum1 + 0.05) / (lum2 + 0.05);\n }\n\n return (lum2 + 0.05) / (lum1 + 0.05);\n },\n level: function (color2) {\n var contrastRatio = this.contrast(color2);\n\n if (contrastRatio >= 7.1) {\n return 'AAA';\n }\n\n return contrastRatio >= 4.5 ? 'AA' : '';\n },\n dark: function () {\n // YIQ equation from http://24ways.org/2010/calculating-color-contrast\n var rgb = this.values.rgb;\n var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000;\n return yiq < 128;\n },\n light: function () {\n return !this.dark();\n },\n negate: function () {\n var rgb = [];\n\n for (var i = 0; i < 3; i++) {\n rgb[i] = 255 - this.values.rgb[i];\n }\n\n this.setValues('rgb', rgb);\n return this;\n },\n lighten: function (ratio) {\n var hsl = this.values.hsl;\n hsl[2] += hsl[2] * ratio;\n this.setValues('hsl', hsl);\n return this;\n },\n darken: function (ratio) {\n var hsl = this.values.hsl;\n hsl[2] -= hsl[2] * ratio;\n this.setValues('hsl', hsl);\n return this;\n },\n saturate: function (ratio) {\n var hsl = this.values.hsl;\n hsl[1] += hsl[1] * ratio;\n this.setValues('hsl', hsl);\n return this;\n },\n desaturate: function (ratio) {\n var hsl = this.values.hsl;\n hsl[1] -= hsl[1] * ratio;\n this.setValues('hsl', hsl);\n return this;\n },\n whiten: function (ratio) {\n var hwb = this.values.hwb;\n hwb[1] += hwb[1] * ratio;\n this.setValues('hwb', hwb);\n return this;\n },\n blacken: function (ratio) {\n var hwb = this.values.hwb;\n hwb[2] += hwb[2] * ratio;\n this.setValues('hwb', hwb);\n return this;\n },\n greyscale: function () {\n var rgb = this.values.rgb; // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale\n\n var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11;\n this.setValues('rgb', [val, val, val]);\n return this;\n },\n clearer: function (ratio) {\n var alpha = this.values.alpha;\n this.setValues('alpha', alpha - alpha * ratio);\n return this;\n },\n opaquer: function (ratio) {\n var alpha = this.values.alpha;\n this.setValues('alpha', alpha + alpha * ratio);\n return this;\n },\n rotate: function (degrees) {\n var hsl = this.values.hsl;\n var hue = (hsl[0] + degrees) % 360;\n hsl[0] = hue < 0 ? 360 + hue : hue;\n this.setValues('hsl', hsl);\n return this;\n },\n\n /**\n * Ported from sass implementation in C\n * https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209\n */\n mix: function (mixinColor, weight) {\n var color1 = this;\n var color2 = mixinColor;\n var p = weight === undefined ? 0.5 : weight;\n var w = 2 * p - 1;\n var a = color1.alpha() - color2.alpha();\n var w1 = ((w * a === -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0;\n var w2 = 1 - w1;\n return this.rgb(w1 * color1.red() + w2 * color2.red(), w1 * color1.green() + w2 * color2.green(), w1 * color1.blue() + w2 * color2.blue()).alpha(color1.alpha() * p + color2.alpha() * (1 - p));\n },\n toJSON: function () {\n return this.rgb();\n },\n clone: function () {\n // NOTE(SB): using node-clone creates a dependency to Buffer when using browserify,\n // making the final build way to big to embed in Chart.js. So let's do it manually,\n // assuming that values to clone are 1 dimension arrays containing only numbers,\n // except 'alpha' which is a number.\n var result = new Color();\n var source = this.values;\n var target = result.values;\n var value, type;\n\n for (var prop in source) {\n if (source.hasOwnProperty(prop)) {\n value = source[prop];\n type = {}.toString.call(value);\n\n if (type === '[object Array]') {\n target[prop] = value.slice(0);\n } else if (type === '[object Number]') {\n target[prop] = value;\n } else {\n console.error('unexpected color value:', value);\n }\n }\n }\n\n return result;\n }\n };\n Color.prototype.spaces = {\n rgb: ['red', 'green', 'blue'],\n hsl: ['hue', 'saturation', 'lightness'],\n hsv: ['hue', 'saturation', 'value'],\n hwb: ['hue', 'whiteness', 'blackness'],\n cmyk: ['cyan', 'magenta', 'yellow', 'black']\n };\n Color.prototype.maxes = {\n rgb: [255, 255, 255],\n hsl: [360, 100, 100],\n hsv: [360, 100, 100],\n hwb: [360, 100, 100],\n cmyk: [100, 100, 100, 100]\n };\n\n Color.prototype.getValues = function (space) {\n var values = this.values;\n var vals = {};\n\n for (var i = 0; i < space.length; i++) {\n vals[space.charAt(i)] = values[space][i];\n }\n\n if (values.alpha !== 1) {\n vals.a = values.alpha;\n } // {r: 255, g: 255, b: 255, a: 0.4}\n\n\n return vals;\n };\n\n Color.prototype.setValues = function (space, vals) {\n var values = this.values;\n var spaces = this.spaces;\n var maxes = this.maxes;\n var alpha = 1;\n var i;\n this.valid = true;\n\n if (space === 'alpha') {\n alpha = vals;\n } else if (vals.length) {\n // [10, 10, 10]\n values[space] = vals.slice(0, space.length);\n alpha = vals[space.length];\n } else if (vals[space.charAt(0)] !== undefined) {\n // {r: 10, g: 10, b: 10}\n for (i = 0; i < space.length; i++) {\n values[space][i] = vals[space.charAt(i)];\n }\n\n alpha = vals.a;\n } else if (vals[spaces[space][0]] !== undefined) {\n // {red: 10, green: 10, blue: 10}\n var chans = spaces[space];\n\n for (i = 0; i < space.length; i++) {\n values[space][i] = vals[chans[i]];\n }\n\n alpha = vals.alpha;\n }\n\n values.alpha = Math.max(0, Math.min(1, alpha === undefined ? values.alpha : alpha));\n\n if (space === 'alpha') {\n return false;\n }\n\n var capped; // cap values of the space prior converting all values\n\n for (i = 0; i < space.length; i++) {\n capped = Math.max(0, Math.min(maxes[space][i], values[space][i]));\n values[space][i] = Math.round(capped);\n } // convert to all the other color spaces\n\n\n for (var sname in spaces) {\n if (sname !== space) {\n values[sname] = colorConvert[space][sname](values[space]);\n }\n }\n\n return true;\n };\n\n Color.prototype.setSpace = function (space, args) {\n var vals = args[0];\n\n if (vals === undefined) {\n // color.rgb()\n return this.getValues(space);\n } // color.rgb(10, 10, 10)\n\n\n if (typeof vals === 'number') {\n vals = Array.prototype.slice.call(args);\n }\n\n this.setValues(space, vals);\n return this;\n };\n\n Color.prototype.setChannel = function (space, index, val) {\n var svalues = this.values[space];\n\n if (val === undefined) {\n // color.red()\n return svalues[index];\n } else if (val === svalues[index]) {\n // color.red(color.red())\n return this;\n } // color.red(100)\n\n\n svalues[index] = val;\n this.setValues(space, svalues);\n return this;\n };\n\n if (typeof window !== 'undefined') {\n window.Color = Color;\n }\n\n var chartjsColor = Color;\n /**\n * @namespace Chart.helpers\n */\n\n var helpers = {\n /**\n * An empty function that can be used, for example, for optional callback.\n */\n noop: function () {},\n\n /**\n * Returns a unique id, sequentially generated from a global variable.\n * @returns {number}\n * @function\n */\n uid: function () {\n var id = 0;\n return function () {\n return id++;\n };\n }(),\n\n /**\n * Returns true if `value` is neither null nor undefined, else returns false.\n * @param {*} value - The value to test.\n * @returns {boolean}\n * @since 2.7.0\n */\n isNullOrUndef: function (value) {\n return value === null || typeof value === 'undefined';\n },\n\n /**\n * Returns true if `value` is an array (including typed arrays), else returns false.\n * @param {*} value - The value to test.\n * @returns {boolean}\n * @function\n */\n isArray: function (value) {\n if (Array.isArray && Array.isArray(value)) {\n return true;\n }\n\n var type = Object.prototype.toString.call(value);\n\n if (type.substr(0, 7) === '[object' && type.substr(-6) === 'Array]') {\n return true;\n }\n\n return false;\n },\n\n /**\n * Returns true if `value` is an object (excluding null), else returns false.\n * @param {*} value - The value to test.\n * @returns {boolean}\n * @since 2.7.0\n */\n isObject: function (value) {\n return value !== null && Object.prototype.toString.call(value) === '[object Object]';\n },\n\n /**\n * Returns true if `value` is a finite number, else returns false\n * @param {*} value - The value to test.\n * @returns {boolean}\n */\n isFinite: function (value) {\n return (typeof value === 'number' || value instanceof Number) && isFinite(value);\n },\n\n /**\n * Returns `value` if defined, else returns `defaultValue`.\n * @param {*} value - The value to return if defined.\n * @param {*} defaultValue - The value to return if `value` is undefined.\n * @returns {*}\n */\n valueOrDefault: function (value, defaultValue) {\n return typeof value === 'undefined' ? defaultValue : value;\n },\n\n /**\n * Returns value at the given `index` in array if defined, else returns `defaultValue`.\n * @param {Array} value - The array to lookup for value at `index`.\n * @param {number} index - The index in `value` to lookup for value.\n * @param {*} defaultValue - The value to return if `value[index]` is undefined.\n * @returns {*}\n */\n valueAtIndexOrDefault: function (value, index, defaultValue) {\n return helpers.valueOrDefault(helpers.isArray(value) ? value[index] : value, defaultValue);\n },\n\n /**\n * Calls `fn` with the given `args` in the scope defined by `thisArg` and returns the\n * value returned by `fn`. If `fn` is not a function, this method returns undefined.\n * @param {function} fn - The function to call.\n * @param {Array|undefined|null} args - The arguments with which `fn` should be called.\n * @param {object} [thisArg] - The value of `this` provided for the call to `fn`.\n * @returns {*}\n */\n callback: function (fn, args, thisArg) {\n if (fn && typeof fn.call === 'function') {\n return fn.apply(thisArg, args);\n }\n },\n\n /**\n * Note(SB) for performance sake, this method should only be used when loopable type\n * is unknown or in none intensive code (not called often and small loopable). Else\n * it's preferable to use a regular for() loop and save extra function calls.\n * @param {object|Array} loopable - The object or array to be iterated.\n * @param {function} fn - The function to call for each item.\n * @param {object} [thisArg] - The value of `this` provided for the call to `fn`.\n * @param {boolean} [reverse] - If true, iterates backward on the loopable.\n */\n each: function (loopable, fn, thisArg, reverse) {\n var i, len, keys;\n\n if (helpers.isArray(loopable)) {\n len = loopable.length;\n\n if (reverse) {\n for (i = len - 1; i >= 0; i--) {\n fn.call(thisArg, loopable[i], i);\n }\n } else {\n for (i = 0; i < len; i++) {\n fn.call(thisArg, loopable[i], i);\n }\n }\n } else if (helpers.isObject(loopable)) {\n keys = Object.keys(loopable);\n len = keys.length;\n\n for (i = 0; i < len; i++) {\n fn.call(thisArg, loopable[keys[i]], keys[i]);\n }\n }\n },\n\n /**\n * Returns true if the `a0` and `a1` arrays have the same content, else returns false.\n * @see https://stackoverflow.com/a/14853974\n * @param {Array} a0 - The array to compare\n * @param {Array} a1 - The array to compare\n * @returns {boolean}\n */\n arrayEquals: function (a0, a1) {\n var i, ilen, v0, v1;\n\n if (!a0 || !a1 || a0.length !== a1.length) {\n return false;\n }\n\n for (i = 0, ilen = a0.length; i < ilen; ++i) {\n v0 = a0[i];\n v1 = a1[i];\n\n if (v0 instanceof Array && v1 instanceof Array) {\n if (!helpers.arrayEquals(v0, v1)) {\n return false;\n }\n } else if (v0 !== v1) {\n // NOTE: two different object instances will never be equal: {x:20} != {x:20}\n return false;\n }\n }\n\n return true;\n },\n\n /**\n * Returns a deep copy of `source` without keeping references on objects and arrays.\n * @param {*} source - The value to clone.\n * @returns {*}\n */\n clone: function (source) {\n if (helpers.isArray(source)) {\n return source.map(helpers.clone);\n }\n\n if (helpers.isObject(source)) {\n var target = {};\n var keys = Object.keys(source);\n var klen = keys.length;\n var k = 0;\n\n for (; k < klen; ++k) {\n target[keys[k]] = helpers.clone(source[keys[k]]);\n }\n\n return target;\n }\n\n return source;\n },\n\n /**\n * The default merger when Chart.helpers.merge is called without merger option.\n * Note(SB): also used by mergeConfig and mergeScaleConfig as fallback.\n * @private\n */\n _merger: function (key, target, source, options) {\n var tval = target[key];\n var sval = source[key];\n\n if (helpers.isObject(tval) && helpers.isObject(sval)) {\n helpers.merge(tval, sval, options);\n } else {\n target[key] = helpers.clone(sval);\n }\n },\n\n /**\n * Merges source[key] in target[key] only if target[key] is undefined.\n * @private\n */\n _mergerIf: function (key, target, source) {\n var tval = target[key];\n var sval = source[key];\n\n if (helpers.isObject(tval) && helpers.isObject(sval)) {\n helpers.mergeIf(tval, sval);\n } else if (!target.hasOwnProperty(key)) {\n target[key] = helpers.clone(sval);\n }\n },\n\n /**\n * Recursively deep copies `source` properties into `target` with the given `options`.\n * IMPORTANT: `target` is not cloned and will be updated with `source` properties.\n * @param {object} target - The target object in which all sources are merged into.\n * @param {object|object[]} source - Object(s) to merge into `target`.\n * @param {object} [options] - Merging options:\n * @param {function} [options.merger] - The merge method (key, target, source, options)\n * @returns {object} The `target` object.\n */\n merge: function (target, source, options) {\n var sources = helpers.isArray(source) ? source : [source];\n var ilen = sources.length;\n var merge, i, keys, klen, k;\n\n if (!helpers.isObject(target)) {\n return target;\n }\n\n options = options || {};\n merge = options.merger || helpers._merger;\n\n for (i = 0; i < ilen; ++i) {\n source = sources[i];\n\n if (!helpers.isObject(source)) {\n continue;\n }\n\n keys = Object.keys(source);\n\n for (k = 0, klen = keys.length; k < klen; ++k) {\n merge(keys[k], target, source, options);\n }\n }\n\n return target;\n },\n\n /**\n * Recursively deep copies `source` properties into `target` *only* if not defined in target.\n * IMPORTANT: `target` is not cloned and will be updated with `source` properties.\n * @param {object} target - The target object in which all sources are merged into.\n * @param {object|object[]} source - Object(s) to merge into `target`.\n * @returns {object} The `target` object.\n */\n mergeIf: function (target, source) {\n return helpers.merge(target, source, {\n merger: helpers._mergerIf\n });\n },\n\n /**\n * Applies the contents of two or more objects together into the first object.\n * @param {object} target - The target object in which all objects are merged into.\n * @param {object} arg1 - Object containing additional properties to merge in target.\n * @param {object} argN - Additional objects containing properties to merge in target.\n * @returns {object} The `target` object.\n */\n extend: Object.assign || function (target) {\n return helpers.merge(target, [].slice.call(arguments, 1), {\n merger: function (key, dst, src) {\n dst[key] = src[key];\n }\n });\n },\n\n /**\n * Basic javascript inheritance based on the model created in Backbone.js\n */\n inherits: function (extensions) {\n var me = this;\n var ChartElement = extensions && extensions.hasOwnProperty('constructor') ? extensions.constructor : function () {\n return me.apply(this, arguments);\n };\n\n var Surrogate = function () {\n this.constructor = ChartElement;\n };\n\n Surrogate.prototype = me.prototype;\n ChartElement.prototype = new Surrogate();\n ChartElement.extend = helpers.inherits;\n\n if (extensions) {\n helpers.extend(ChartElement.prototype, extensions);\n }\n\n ChartElement.__super__ = me.prototype;\n return ChartElement;\n },\n _deprecated: function (scope, value, previous, current) {\n if (value !== undefined) {\n console.warn(scope + ': \"' + previous + '\" is deprecated. Please use \"' + current + '\" instead');\n }\n }\n };\n var helpers_core = helpers; // DEPRECATIONS\n\n /**\n * Provided for backward compatibility, use Chart.helpers.callback instead.\n * @function Chart.helpers.callCallback\n * @deprecated since version 2.6.0\n * @todo remove at version 3\n * @private\n */\n\n helpers.callCallback = helpers.callback;\n /**\n * Provided for backward compatibility, use Array.prototype.indexOf instead.\n * Array.prototype.indexOf compatibility: Chrome, Opera, Safari, FF1.5+, IE9+\n * @function Chart.helpers.indexOf\n * @deprecated since version 2.7.0\n * @todo remove at version 3\n * @private\n */\n\n helpers.indexOf = function (array, item, fromIndex) {\n return Array.prototype.indexOf.call(array, item, fromIndex);\n };\n /**\n * Provided for backward compatibility, use Chart.helpers.valueOrDefault instead.\n * @function Chart.helpers.getValueOrDefault\n * @deprecated since version 2.7.0\n * @todo remove at version 3\n * @private\n */\n\n\n helpers.getValueOrDefault = helpers.valueOrDefault;\n /**\n * Provided for backward compatibility, use Chart.helpers.valueAtIndexOrDefault instead.\n * @function Chart.helpers.getValueAtIndexOrDefault\n * @deprecated since version 2.7.0\n * @todo remove at version 3\n * @private\n */\n\n helpers.getValueAtIndexOrDefault = helpers.valueAtIndexOrDefault;\n /**\n * Easing functions adapted from Robert Penner's easing equations.\n * @namespace Chart.helpers.easingEffects\n * @see http://www.robertpenner.com/easing/\n */\n\n var effects = {\n linear: function (t) {\n return t;\n },\n easeInQuad: function (t) {\n return t * t;\n },\n easeOutQuad: function (t) {\n return -t * (t - 2);\n },\n easeInOutQuad: function (t) {\n if ((t /= 0.5) < 1) {\n return 0.5 * t * t;\n }\n\n return -0.5 * (--t * (t - 2) - 1);\n },\n easeInCubic: function (t) {\n return t * t * t;\n },\n easeOutCubic: function (t) {\n return (t = t - 1) * t * t + 1;\n },\n easeInOutCubic: function (t) {\n if ((t /= 0.5) < 1) {\n return 0.5 * t * t * t;\n }\n\n return 0.5 * ((t -= 2) * t * t + 2);\n },\n easeInQuart: function (t) {\n return t * t * t * t;\n },\n easeOutQuart: function (t) {\n return -((t = t - 1) * t * t * t - 1);\n },\n easeInOutQuart: function (t) {\n if ((t /= 0.5) < 1) {\n return 0.5 * t * t * t * t;\n }\n\n return -0.5 * ((t -= 2) * t * t * t - 2);\n },\n easeInQuint: function (t) {\n return t * t * t * t * t;\n },\n easeOutQuint: function (t) {\n return (t = t - 1) * t * t * t * t + 1;\n },\n easeInOutQuint: function (t) {\n if ((t /= 0.5) < 1) {\n return 0.5 * t * t * t * t * t;\n }\n\n return 0.5 * ((t -= 2) * t * t * t * t + 2);\n },\n easeInSine: function (t) {\n return -Math.cos(t * (Math.PI / 2)) + 1;\n },\n easeOutSine: function (t) {\n return Math.sin(t * (Math.PI / 2));\n },\n easeInOutSine: function (t) {\n return -0.5 * (Math.cos(Math.PI * t) - 1);\n },\n easeInExpo: function (t) {\n return t === 0 ? 0 : Math.pow(2, 10 * (t - 1));\n },\n easeOutExpo: function (t) {\n return t === 1 ? 1 : -Math.pow(2, -10 * t) + 1;\n },\n easeInOutExpo: function (t) {\n if (t === 0) {\n return 0;\n }\n\n if (t === 1) {\n return 1;\n }\n\n if ((t /= 0.5) < 1) {\n return 0.5 * Math.pow(2, 10 * (t - 1));\n }\n\n return 0.5 * (-Math.pow(2, -10 * --t) + 2);\n },\n easeInCirc: function (t) {\n if (t >= 1) {\n return t;\n }\n\n return -(Math.sqrt(1 - t * t) - 1);\n },\n easeOutCirc: function (t) {\n return Math.sqrt(1 - (t = t - 1) * t);\n },\n easeInOutCirc: function (t) {\n if ((t /= 0.5) < 1) {\n return -0.5 * (Math.sqrt(1 - t * t) - 1);\n }\n\n return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1);\n },\n easeInElastic: function (t) {\n var s = 1.70158;\n var p = 0;\n var a = 1;\n\n if (t === 0) {\n return 0;\n }\n\n if (t === 1) {\n return 1;\n }\n\n if (!p) {\n p = 0.3;\n }\n\n if (a < 1) {\n a = 1;\n s = p / 4;\n } else {\n s = p / (2 * Math.PI) * Math.asin(1 / a);\n }\n\n return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p));\n },\n easeOutElastic: function (t) {\n var s = 1.70158;\n var p = 0;\n var a = 1;\n\n if (t === 0) {\n return 0;\n }\n\n if (t === 1) {\n return 1;\n }\n\n if (!p) {\n p = 0.3;\n }\n\n if (a < 1) {\n a = 1;\n s = p / 4;\n } else {\n s = p / (2 * Math.PI) * Math.asin(1 / a);\n }\n\n return a * Math.pow(2, -10 * t) * Math.sin((t - s) * (2 * Math.PI) / p) + 1;\n },\n easeInOutElastic: function (t) {\n var s = 1.70158;\n var p = 0;\n var a = 1;\n\n if (t === 0) {\n return 0;\n }\n\n if ((t /= 0.5) === 2) {\n return 1;\n }\n\n if (!p) {\n p = 0.45;\n }\n\n if (a < 1) {\n a = 1;\n s = p / 4;\n } else {\n s = p / (2 * Math.PI) * Math.asin(1 / a);\n }\n\n if (t < 1) {\n return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p));\n }\n\n return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p) * 0.5 + 1;\n },\n easeInBack: function (t) {\n var s = 1.70158;\n return t * t * ((s + 1) * t - s);\n },\n easeOutBack: function (t) {\n var s = 1.70158;\n return (t = t - 1) * t * ((s + 1) * t + s) + 1;\n },\n easeInOutBack: function (t) {\n var s = 1.70158;\n\n if ((t /= 0.5) < 1) {\n return 0.5 * (t * t * (((s *= 1.525) + 1) * t - s));\n }\n\n return 0.5 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2);\n },\n easeInBounce: function (t) {\n return 1 - effects.easeOutBounce(1 - t);\n },\n easeOutBounce: function (t) {\n if (t < 1 / 2.75) {\n return 7.5625 * t * t;\n }\n\n if (t < 2 / 2.75) {\n return 7.5625 * (t -= 1.5 / 2.75) * t + 0.75;\n }\n\n if (t < 2.5 / 2.75) {\n return 7.5625 * (t -= 2.25 / 2.75) * t + 0.9375;\n }\n\n return 7.5625 * (t -= 2.625 / 2.75) * t + 0.984375;\n },\n easeInOutBounce: function (t) {\n if (t < 0.5) {\n return effects.easeInBounce(t * 2) * 0.5;\n }\n\n return effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5;\n }\n };\n var helpers_easing = {\n effects: effects\n }; // DEPRECATIONS\n\n /**\n * Provided for backward compatibility, use Chart.helpers.easing.effects instead.\n * @function Chart.helpers.easingEffects\n * @deprecated since version 2.7.0\n * @todo remove at version 3\n * @private\n */\n\n helpers_core.easingEffects = effects;\n var PI = Math.PI;\n var RAD_PER_DEG = PI / 180;\n var DOUBLE_PI = PI * 2;\n var HALF_PI = PI / 2;\n var QUARTER_PI = PI / 4;\n var TWO_THIRDS_PI = PI * 2 / 3;\n /**\n * @namespace Chart.helpers.canvas\n */\n\n var exports$1 = {\n /**\n * Clears the entire canvas associated to the given `chart`.\n * @param {Chart} chart - The chart for which to clear the canvas.\n */\n clear: function (chart) {\n chart.ctx.clearRect(0, 0, chart.width, chart.height);\n },\n\n /**\n * Creates a \"path\" for a rectangle with rounded corners at position (x, y) with a\n * given size (width, height) and the same `radius` for all corners.\n * @param {CanvasRenderingContext2D} ctx - The canvas 2D Context.\n * @param {number} x - The x axis of the coordinate for the rectangle starting point.\n * @param {number} y - The y axis of the coordinate for the rectangle starting point.\n * @param {number} width - The rectangle's width.\n * @param {number} height - The rectangle's height.\n * @param {number} radius - The rounded amount (in pixels) for the four corners.\n * @todo handle `radius` as top-left, top-right, bottom-right, bottom-left array/object?\n */\n roundedRect: function (ctx, x, y, width, height, radius) {\n if (radius) {\n var r = Math.min(radius, height / 2, width / 2);\n var left = x + r;\n var top = y + r;\n var right = x + width - r;\n var bottom = y + height - r;\n ctx.moveTo(x, top);\n\n if (left < right && top < bottom) {\n ctx.arc(left, top, r, -PI, -HALF_PI);\n ctx.arc(right, top, r, -HALF_PI, 0);\n ctx.arc(right, bottom, r, 0, HALF_PI);\n ctx.arc(left, bottom, r, HALF_PI, PI);\n } else if (left < right) {\n ctx.moveTo(left, y);\n ctx.arc(right, top, r, -HALF_PI, HALF_PI);\n ctx.arc(left, top, r, HALF_PI, PI + HALF_PI);\n } else if (top < bottom) {\n ctx.arc(left, top, r, -PI, 0);\n ctx.arc(left, bottom, r, 0, PI);\n } else {\n ctx.arc(left, top, r, -PI, PI);\n }\n\n ctx.closePath();\n ctx.moveTo(x, y);\n } else {\n ctx.rect(x, y, width, height);\n }\n },\n drawPoint: function (ctx, style, radius, x, y, rotation) {\n var type, xOffset, yOffset, size, cornerRadius;\n var rad = (rotation || 0) * RAD_PER_DEG;\n\n if (style && typeof style === 'object') {\n type = style.toString();\n\n if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {\n ctx.save();\n ctx.translate(x, y);\n ctx.rotate(rad);\n ctx.drawImage(style, -style.width / 2, -style.height / 2, style.width, style.height);\n ctx.restore();\n return;\n }\n }\n\n if (isNaN(radius) || radius <= 0) {\n return;\n }\n\n ctx.beginPath();\n\n switch (style) {\n // Default includes circle\n default:\n ctx.arc(x, y, radius, 0, DOUBLE_PI);\n ctx.closePath();\n break;\n\n case 'triangle':\n ctx.moveTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);\n rad += TWO_THIRDS_PI;\n ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);\n rad += TWO_THIRDS_PI;\n ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);\n ctx.closePath();\n break;\n\n case 'rectRounded':\n // NOTE: the rounded rect implementation changed to use `arc` instead of\n // `quadraticCurveTo` since it generates better results when rect is\n // almost a circle. 0.516 (instead of 0.5) produces results with visually\n // closer proportion to the previous impl and it is inscribed in the\n // circle with `radius`. For more details, see the following PRs:\n // https://github.com/chartjs/Chart.js/issues/5597\n // https://github.com/chartjs/Chart.js/issues/5858\n cornerRadius = radius * 0.516;\n size = radius - cornerRadius;\n xOffset = Math.cos(rad + QUARTER_PI) * size;\n yOffset = Math.sin(rad + QUARTER_PI) * size;\n ctx.arc(x - xOffset, y - yOffset, cornerRadius, rad - PI, rad - HALF_PI);\n ctx.arc(x + yOffset, y - xOffset, cornerRadius, rad - HALF_PI, rad);\n ctx.arc(x + xOffset, y + yOffset, cornerRadius, rad, rad + HALF_PI);\n ctx.arc(x - yOffset, y + xOffset, cornerRadius, rad + HALF_PI, rad + PI);\n ctx.closePath();\n break;\n\n case 'rect':\n if (!rotation) {\n size = Math.SQRT1_2 * radius;\n ctx.rect(x - size, y - size, 2 * size, 2 * size);\n break;\n }\n\n rad += QUARTER_PI;\n\n /* falls through */\n\n case 'rectRot':\n xOffset = Math.cos(rad) * radius;\n yOffset = Math.sin(rad) * radius;\n ctx.moveTo(x - xOffset, y - yOffset);\n ctx.lineTo(x + yOffset, y - xOffset);\n ctx.lineTo(x + xOffset, y + yOffset);\n ctx.lineTo(x - yOffset, y + xOffset);\n ctx.closePath();\n break;\n\n case 'crossRot':\n rad += QUARTER_PI;\n\n /* falls through */\n\n case 'cross':\n xOffset = Math.cos(rad) * radius;\n yOffset = Math.sin(rad) * radius;\n ctx.moveTo(x - xOffset, y - yOffset);\n ctx.lineTo(x + xOffset, y + yOffset);\n ctx.moveTo(x + yOffset, y - xOffset);\n ctx.lineTo(x - yOffset, y + xOffset);\n break;\n\n case 'star':\n xOffset = Math.cos(rad) * radius;\n yOffset = Math.sin(rad) * radius;\n ctx.moveTo(x - xOffset, y - yOffset);\n ctx.lineTo(x + xOffset, y + yOffset);\n ctx.moveTo(x + yOffset, y - xOffset);\n ctx.lineTo(x - yOffset, y + xOffset);\n rad += QUARTER_PI;\n xOffset = Math.cos(rad) * radius;\n yOffset = Math.sin(rad) * radius;\n ctx.moveTo(x - xOffset, y - yOffset);\n ctx.lineTo(x + xOffset, y + yOffset);\n ctx.moveTo(x + yOffset, y - xOffset);\n ctx.lineTo(x - yOffset, y + xOffset);\n break;\n\n case 'line':\n xOffset = Math.cos(rad) * radius;\n yOffset = Math.sin(rad) * radius;\n ctx.moveTo(x - xOffset, y - yOffset);\n ctx.lineTo(x + xOffset, y + yOffset);\n break;\n\n case 'dash':\n ctx.moveTo(x, y);\n ctx.lineTo(x + Math.cos(rad) * radius, y + Math.sin(rad) * radius);\n break;\n }\n\n ctx.fill();\n ctx.stroke();\n },\n\n /**\n * Returns true if the point is inside the rectangle\n * @param {object} point - The point to test\n * @param {object} area - The rectangle\n * @returns {boolean}\n * @private\n */\n _isPointInArea: function (point, area) {\n var epsilon = 1e-6; // 1e-6 is margin in pixels for accumulated error.\n\n return point.x > area.left - epsilon && point.x < area.right + epsilon && point.y > area.top - epsilon && point.y < area.bottom + epsilon;\n },\n clipArea: function (ctx, area) {\n ctx.save();\n ctx.beginPath();\n ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top);\n ctx.clip();\n },\n unclipArea: function (ctx) {\n ctx.restore();\n },\n lineTo: function (ctx, previous, target, flip) {\n var stepped = target.steppedLine;\n\n if (stepped) {\n if (stepped === 'middle') {\n var midpoint = (previous.x + target.x) / 2.0;\n ctx.lineTo(midpoint, flip ? target.y : previous.y);\n ctx.lineTo(midpoint, flip ? previous.y : target.y);\n } else if (stepped === 'after' && !flip || stepped !== 'after' && flip) {\n ctx.lineTo(previous.x, target.y);\n } else {\n ctx.lineTo(target.x, previous.y);\n }\n\n ctx.lineTo(target.x, target.y);\n return;\n }\n\n if (!target.tension) {\n ctx.lineTo(target.x, target.y);\n return;\n }\n\n ctx.bezierCurveTo(flip ? previous.controlPointPreviousX : previous.controlPointNextX, flip ? previous.controlPointPreviousY : previous.controlPointNextY, flip ? target.controlPointNextX : target.controlPointPreviousX, flip ? target.controlPointNextY : target.controlPointPreviousY, target.x, target.y);\n }\n };\n var helpers_canvas = exports$1; // DEPRECATIONS\n\n /**\n * Provided for backward compatibility, use Chart.helpers.canvas.clear instead.\n * @namespace Chart.helpers.clear\n * @deprecated since version 2.7.0\n * @todo remove at version 3\n * @private\n */\n\n helpers_core.clear = exports$1.clear;\n /**\n * Provided for backward compatibility, use Chart.helpers.canvas.roundedRect instead.\n * @namespace Chart.helpers.drawRoundedRectangle\n * @deprecated since version 2.7.0\n * @todo remove at version 3\n * @private\n */\n\n helpers_core.drawRoundedRectangle = function (ctx) {\n ctx.beginPath();\n exports$1.roundedRect.apply(exports$1, arguments);\n };\n\n var defaults = {\n /**\n * @private\n */\n _set: function (scope, values) {\n return helpers_core.merge(this[scope] || (this[scope] = {}), values);\n }\n }; // TODO(v3): remove 'global' from namespace. all default are global and\n // there's inconsistency around which options are under 'global'\n\n defaults._set('global', {\n defaultColor: 'rgba(0,0,0,0.1)',\n defaultFontColor: '#666',\n defaultFontFamily: \"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif\",\n defaultFontSize: 12,\n defaultFontStyle: 'normal',\n defaultLineHeight: 1.2,\n showLines: true\n });\n\n var core_defaults = defaults;\n var valueOrDefault = helpers_core.valueOrDefault;\n /**\n * Converts the given font object into a CSS font string.\n * @param {object} font - A font object.\n * @return {string} The CSS font string. See https://developer.mozilla.org/en-US/docs/Web/CSS/font\n * @private\n */\n\n function toFontString(font) {\n if (!font || helpers_core.isNullOrUndef(font.size) || helpers_core.isNullOrUndef(font.family)) {\n return null;\n }\n\n return (font.style ? font.style + ' ' : '') + (font.weight ? font.weight + ' ' : '') + font.size + 'px ' + font.family;\n }\n /**\n * @alias Chart.helpers.options\n * @namespace\n */\n\n\n var helpers_options = {\n /**\n * Converts the given line height `value` in pixels for a specific font `size`.\n * @param {number|string} value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em').\n * @param {number} size - The font size (in pixels) used to resolve relative `value`.\n * @returns {number} The effective line height in pixels (size * 1.2 if value is invalid).\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height\n * @since 2.7.0\n */\n toLineHeight: function (value, size) {\n var matches = ('' + value).match(/^(normal|(\\d+(?:\\.\\d+)?)(px|em|%)?)$/);\n\n if (!matches || matches[1] === 'normal') {\n return size * 1.2;\n }\n\n value = +matches[2];\n\n switch (matches[3]) {\n case 'px':\n return value;\n\n case '%':\n value /= 100;\n break;\n }\n\n return size * value;\n },\n\n /**\n * Converts the given value into a padding object with pre-computed width/height.\n * @param {number|object} value - If a number, set the value to all TRBL component,\n * else, if and object, use defined properties and sets undefined ones to 0.\n * @returns {object} The padding values (top, right, bottom, left, width, height)\n * @since 2.7.0\n */\n toPadding: function (value) {\n var t, r, b, l;\n\n if (helpers_core.isObject(value)) {\n t = +value.top || 0;\n r = +value.right || 0;\n b = +value.bottom || 0;\n l = +value.left || 0;\n } else {\n t = r = b = l = +value || 0;\n }\n\n return {\n top: t,\n right: r,\n bottom: b,\n left: l,\n height: t + b,\n width: l + r\n };\n },\n\n /**\n * Parses font options and returns the font object.\n * @param {object} options - A object that contains font options to be parsed.\n * @return {object} The font object.\n * @todo Support font.* options and renamed to toFont().\n * @private\n */\n _parseFont: function (options) {\n var globalDefaults = core_defaults.global;\n var size = valueOrDefault(options.fontSize, globalDefaults.defaultFontSize);\n var font = {\n family: valueOrDefault(options.fontFamily, globalDefaults.defaultFontFamily),\n lineHeight: helpers_core.options.toLineHeight(valueOrDefault(options.lineHeight, globalDefaults.defaultLineHeight), size),\n size: size,\n style: valueOrDefault(options.fontStyle, globalDefaults.defaultFontStyle),\n weight: null,\n string: ''\n };\n font.string = toFontString(font);\n return font;\n },\n\n /**\n * Evaluates the given `inputs` sequentially and returns the first defined value.\n * @param {Array} inputs - An array of values, falling back to the last value.\n * @param {object} [context] - If defined and the current value is a function, the value\n * is called with `context` as first argument and the result becomes the new input.\n * @param {number} [index] - If defined and the current value is an array, the value\n * at `index` become the new input.\n * @param {object} [info] - object to return information about resolution in\n * @param {boolean} [info.cacheable] - Will be set to `false` if option is not cacheable.\n * @since 2.7.0\n */\n resolve: function (inputs, context, index, info) {\n var cacheable = true;\n var i, ilen, value;\n\n for (i = 0, ilen = inputs.length; i < ilen; ++i) {\n value = inputs[i];\n\n if (value === undefined) {\n continue;\n }\n\n if (context !== undefined && typeof value === 'function') {\n value = value(context);\n cacheable = false;\n }\n\n if (index !== undefined && helpers_core.isArray(value)) {\n value = value[index];\n cacheable = false;\n }\n\n if (value !== undefined) {\n if (info && !cacheable) {\n info.cacheable = false;\n }\n\n return value;\n }\n }\n }\n };\n /**\n * @alias Chart.helpers.math\n * @namespace\n */\n\n var exports$2 = {\n /**\n * Returns an array of factors sorted from 1 to sqrt(value)\n * @private\n */\n _factorize: function (value) {\n var result = [];\n var sqrt = Math.sqrt(value);\n var i;\n\n for (i = 1; i < sqrt; i++) {\n if (value % i === 0) {\n result.push(i);\n result.push(value / i);\n }\n }\n\n if (sqrt === (sqrt | 0)) {\n // if value is a square number\n result.push(sqrt);\n }\n\n result.sort(function (a, b) {\n return a - b;\n }).pop();\n return result;\n },\n log10: Math.log10 || function (x) {\n var exponent = Math.log(x) * Math.LOG10E; // Math.LOG10E = 1 / Math.LN10.\n // Check for whole powers of 10,\n // which due to floating point rounding error should be corrected.\n\n var powerOf10 = Math.round(exponent);\n var isPowerOf10 = x === Math.pow(10, powerOf10);\n return isPowerOf10 ? powerOf10 : exponent;\n }\n };\n var helpers_math = exports$2; // DEPRECATIONS\n\n /**\n * Provided for backward compatibility, use Chart.helpers.math.log10 instead.\n * @namespace Chart.helpers.log10\n * @deprecated since version 2.9.0\n * @todo remove at version 3\n * @private\n */\n\n helpers_core.log10 = exports$2.log10;\n\n var getRtlAdapter = function (rectX, width) {\n return {\n x: function (x) {\n return rectX + rectX + width - x;\n },\n setWidth: function (w) {\n width = w;\n },\n textAlign: function (align) {\n if (align === 'center') {\n return align;\n }\n\n return align === 'right' ? 'left' : 'right';\n },\n xPlus: function (x, value) {\n return x - value;\n },\n leftForLtr: function (x, itemWidth) {\n return x - itemWidth;\n }\n };\n };\n\n var getLtrAdapter = function () {\n return {\n x: function (x) {\n return x;\n },\n setWidth: function (w) {// eslint-disable-line no-unused-vars\n },\n textAlign: function (align) {\n return align;\n },\n xPlus: function (x, value) {\n return x + value;\n },\n leftForLtr: function (x, _itemWidth) {\n // eslint-disable-line no-unused-vars\n return x;\n }\n };\n };\n\n var getAdapter = function (rtl, rectX, width) {\n return rtl ? getRtlAdapter(rectX, width) : getLtrAdapter();\n };\n\n var overrideTextDirection = function (ctx, direction) {\n var style, original;\n\n if (direction === 'ltr' || direction === 'rtl') {\n style = ctx.canvas.style;\n original = [style.getPropertyValue('direction'), style.getPropertyPriority('direction')];\n style.setProperty('direction', direction, 'important');\n ctx.prevTextDirection = original;\n }\n };\n\n var restoreTextDirection = function (ctx) {\n var original = ctx.prevTextDirection;\n\n if (original !== undefined) {\n delete ctx.prevTextDirection;\n ctx.canvas.style.setProperty('direction', original[0], original[1]);\n }\n };\n\n var helpers_rtl = {\n getRtlAdapter: getAdapter,\n overrideTextDirection: overrideTextDirection,\n restoreTextDirection: restoreTextDirection\n };\n var helpers$1 = helpers_core;\n var easing = helpers_easing;\n var canvas = helpers_canvas;\n var options = helpers_options;\n var math = helpers_math;\n var rtl = helpers_rtl;\n helpers$1.easing = easing;\n helpers$1.canvas = canvas;\n helpers$1.options = options;\n helpers$1.math = math;\n helpers$1.rtl = rtl;\n\n function interpolate(start, view, model, ease) {\n var keys = Object.keys(model);\n var i, ilen, key, actual, origin, target, type, c0, c1;\n\n for (i = 0, ilen = keys.length; i < ilen; ++i) {\n key = keys[i];\n target = model[key]; // if a value is added to the model after pivot() has been called, the view\n // doesn't contain it, so let's initialize the view to the target value.\n\n if (!view.hasOwnProperty(key)) {\n view[key] = target;\n }\n\n actual = view[key];\n\n if (actual === target || key[0] === '_') {\n continue;\n }\n\n if (!start.hasOwnProperty(key)) {\n start[key] = actual;\n }\n\n origin = start[key];\n type = typeof target;\n\n if (type === typeof origin) {\n if (type === 'string') {\n c0 = chartjsColor(origin);\n\n if (c0.valid) {\n c1 = chartjsColor(target);\n\n if (c1.valid) {\n view[key] = c1.mix(c0, ease).rgbString();\n continue;\n }\n }\n } else if (helpers$1.isFinite(origin) && helpers$1.isFinite(target)) {\n view[key] = origin + (target - origin) * ease;\n continue;\n }\n }\n\n view[key] = target;\n }\n }\n\n var Element = function (configuration) {\n helpers$1.extend(this, configuration);\n this.initialize.apply(this, arguments);\n };\n\n helpers$1.extend(Element.prototype, {\n _type: undefined,\n initialize: function () {\n this.hidden = false;\n },\n pivot: function () {\n var me = this;\n\n if (!me._view) {\n me._view = helpers$1.extend({}, me._model);\n }\n\n me._start = {};\n return me;\n },\n transition: function (ease) {\n var me = this;\n var model = me._model;\n var start = me._start;\n var view = me._view; // No animation -> No Transition\n\n if (!model || ease === 1) {\n me._view = helpers$1.extend({}, model);\n me._start = null;\n return me;\n }\n\n if (!view) {\n view = me._view = {};\n }\n\n if (!start) {\n start = me._start = {};\n }\n\n interpolate(start, view, model, ease);\n return me;\n },\n tooltipPosition: function () {\n return {\n x: this._model.x,\n y: this._model.y\n };\n },\n hasValue: function () {\n return helpers$1.isNumber(this._model.x) && helpers$1.isNumber(this._model.y);\n }\n });\n Element.extend = helpers$1.inherits;\n var core_element = Element;\n var exports$3 = core_element.extend({\n chart: null,\n // the animation associated chart instance\n currentStep: 0,\n // the current animation step\n numSteps: 60,\n // default number of steps\n easing: '',\n // the easing to use for this animation\n render: null,\n // render function used by the animation service\n onAnimationProgress: null,\n // user specified callback to fire on each step of the animation\n onAnimationComplete: null // user specified callback to fire when the animation finishes\n\n });\n var core_animation = exports$3; // DEPRECATIONS\n\n /**\n * Provided for backward compatibility, use Chart.Animation instead\n * @prop Chart.Animation#animationObject\n * @deprecated since version 2.6.0\n * @todo remove at version 3\n */\n\n Object.defineProperty(exports$3.prototype, 'animationObject', {\n get: function () {\n return this;\n }\n });\n /**\n * Provided for backward compatibility, use Chart.Animation#chart instead\n * @prop Chart.Animation#chartInstance\n * @deprecated since version 2.6.0\n * @todo remove at version 3\n */\n\n Object.defineProperty(exports$3.prototype, 'chartInstance', {\n get: function () {\n return this.chart;\n },\n set: function (value) {\n this.chart = value;\n }\n });\n\n core_defaults._set('global', {\n animation: {\n duration: 1000,\n easing: 'easeOutQuart',\n onProgress: helpers$1.noop,\n onComplete: helpers$1.noop\n }\n });\n\n var core_animations = {\n animations: [],\n request: null,\n\n /**\n * @param {Chart} chart - The chart to animate.\n * @param {Chart.Animation} animation - The animation that we will animate.\n * @param {number} duration - The animation duration in ms.\n * @param {boolean} lazy - if true, the chart is not marked as animating to enable more responsive interactions\n */\n addAnimation: function (chart, animation, duration, lazy) {\n var animations = this.animations;\n var i, ilen;\n animation.chart = chart;\n animation.startTime = Date.now();\n animation.duration = duration;\n\n if (!lazy) {\n chart.animating = true;\n }\n\n for (i = 0, ilen = animations.length; i < ilen; ++i) {\n if (animations[i].chart === chart) {\n animations[i] = animation;\n return;\n }\n }\n\n animations.push(animation); // If there are no animations queued, manually kickstart a digest, for lack of a better word\n\n if (animations.length === 1) {\n this.requestAnimationFrame();\n }\n },\n cancelAnimation: function (chart) {\n var index = helpers$1.findIndex(this.animations, function (animation) {\n return animation.chart === chart;\n });\n\n if (index !== -1) {\n this.animations.splice(index, 1);\n chart.animating = false;\n }\n },\n requestAnimationFrame: function () {\n var me = this;\n\n if (me.request === null) {\n // Skip animation frame requests until the active one is executed.\n // This can happen when processing mouse events, e.g. 'mousemove'\n // and 'mouseout' events will trigger multiple renders.\n me.request = helpers$1.requestAnimFrame.call(window, function () {\n me.request = null;\n me.startDigest();\n });\n }\n },\n\n /**\n * @private\n */\n startDigest: function () {\n var me = this;\n me.advance(); // Do we have more stuff to animate?\n\n if (me.animations.length > 0) {\n me.requestAnimationFrame();\n }\n },\n\n /**\n * @private\n */\n advance: function () {\n var animations = this.animations;\n var animation, chart, numSteps, nextStep;\n var i = 0; // 1 animation per chart, so we are looping charts here\n\n while (i < animations.length) {\n animation = animations[i];\n chart = animation.chart;\n numSteps = animation.numSteps; // Make sure that currentStep starts at 1\n // https://github.com/chartjs/Chart.js/issues/6104\n\n nextStep = Math.floor((Date.now() - animation.startTime) / animation.duration * numSteps) + 1;\n animation.currentStep = Math.min(nextStep, numSteps);\n helpers$1.callback(animation.render, [chart, animation], chart);\n helpers$1.callback(animation.onAnimationProgress, [animation], chart);\n\n if (animation.currentStep >= numSteps) {\n helpers$1.callback(animation.onAnimationComplete, [animation], chart);\n chart.animating = false;\n animations.splice(i, 1);\n } else {\n ++i;\n }\n }\n }\n };\n var resolve = helpers$1.options.resolve;\n var arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift'];\n /**\n * Hooks the array methods that add or remove values ('push', pop', 'shift', 'splice',\n * 'unshift') and notify the listener AFTER the array has been altered. Listeners are\n * called on the 'onData*' callbacks (e.g. onDataPush, etc.) with same arguments.\n */\n\n function listenArrayEvents(array, listener) {\n if (array._chartjs) {\n array._chartjs.listeners.push(listener);\n\n return;\n }\n\n Object.defineProperty(array, '_chartjs', {\n configurable: true,\n enumerable: false,\n value: {\n listeners: [listener]\n }\n });\n arrayEvents.forEach(function (key) {\n var method = 'onData' + key.charAt(0).toUpperCase() + key.slice(1);\n var base = array[key];\n Object.defineProperty(array, key, {\n configurable: true,\n enumerable: false,\n value: function () {\n var args = Array.prototype.slice.call(arguments);\n var res = base.apply(this, args);\n helpers$1.each(array._chartjs.listeners, function (object) {\n if (typeof object[method] === 'function') {\n object[method].apply(object, args);\n }\n });\n return res;\n }\n });\n });\n }\n /**\n * Removes the given array event listener and cleanup extra attached properties (such as\n * the _chartjs stub and overridden methods) if array doesn't have any more listeners.\n */\n\n\n function unlistenArrayEvents(array, listener) {\n var stub = array._chartjs;\n\n if (!stub) {\n return;\n }\n\n var listeners = stub.listeners;\n var index = listeners.indexOf(listener);\n\n if (index !== -1) {\n listeners.splice(index, 1);\n }\n\n if (listeners.length > 0) {\n return;\n }\n\n arrayEvents.forEach(function (key) {\n delete array[key];\n });\n delete array._chartjs;\n } // Base class for all dataset controllers (line, bar, etc)\n\n\n var DatasetController = function (chart, datasetIndex) {\n this.initialize(chart, datasetIndex);\n };\n\n helpers$1.extend(DatasetController.prototype, {\n /**\n * Element type used to generate a meta dataset (e.g. Chart.element.Line).\n * @type {Chart.core.element}\n */\n datasetElementType: null,\n\n /**\n * Element type used to generate a meta data (e.g. Chart.element.Point).\n * @type {Chart.core.element}\n */\n dataElementType: null,\n\n /**\n * Dataset element option keys to be resolved in _resolveDatasetElementOptions.\n * A derived controller may override this to resolve controller-specific options.\n * The keys defined here are for backward compatibility for legend styles.\n * @private\n */\n _datasetElementOptions: ['backgroundColor', 'borderCapStyle', 'borderColor', 'borderDash', 'borderDashOffset', 'borderJoinStyle', 'borderWidth'],\n\n /**\n * Data element option keys to be resolved in _resolveDataElementOptions.\n * A derived controller may override this to resolve controller-specific options.\n * The keys defined here are for backward compatibility for legend styles.\n * @private\n */\n _dataElementOptions: ['backgroundColor', 'borderColor', 'borderWidth', 'pointStyle'],\n initialize: function (chart, datasetIndex) {\n var me = this;\n me.chart = chart;\n me.index = datasetIndex;\n me.linkScales();\n me.addElements();\n me._type = me.getMeta().type;\n },\n updateIndex: function (datasetIndex) {\n this.index = datasetIndex;\n },\n linkScales: function () {\n var me = this;\n var meta = me.getMeta();\n var chart = me.chart;\n var scales = chart.scales;\n var dataset = me.getDataset();\n var scalesOpts = chart.options.scales;\n\n if (meta.xAxisID === null || !(meta.xAxisID in scales) || dataset.xAxisID) {\n meta.xAxisID = dataset.xAxisID || scalesOpts.xAxes[0].id;\n }\n\n if (meta.yAxisID === null || !(meta.yAxisID in scales) || dataset.yAxisID) {\n meta.yAxisID = dataset.yAxisID || scalesOpts.yAxes[0].id;\n }\n },\n getDataset: function () {\n return this.chart.data.datasets[this.index];\n },\n getMeta: function () {\n return this.chart.getDatasetMeta(this.index);\n },\n getScaleForId: function (scaleID) {\n return this.chart.scales[scaleID];\n },\n\n /**\n * @private\n */\n _getValueScaleId: function () {\n return this.getMeta().yAxisID;\n },\n\n /**\n * @private\n */\n _getIndexScaleId: function () {\n return this.getMeta().xAxisID;\n },\n\n /**\n * @private\n */\n _getValueScale: function () {\n return this.getScaleForId(this._getValueScaleId());\n },\n\n /**\n * @private\n */\n _getIndexScale: function () {\n return this.getScaleForId(this._getIndexScaleId());\n },\n reset: function () {\n this._update(true);\n },\n\n /**\n * @private\n */\n destroy: function () {\n if (this._data) {\n unlistenArrayEvents(this._data, this);\n }\n },\n createMetaDataset: function () {\n var me = this;\n var type = me.datasetElementType;\n return type && new type({\n _chart: me.chart,\n _datasetIndex: me.index\n });\n },\n createMetaData: function (index) {\n var me = this;\n var type = me.dataElementType;\n return type && new type({\n _chart: me.chart,\n _datasetIndex: me.index,\n _index: index\n });\n },\n addElements: function () {\n var me = this;\n var meta = me.getMeta();\n var data = me.getDataset().data || [];\n var metaData = meta.data;\n var i, ilen;\n\n for (i = 0, ilen = data.length; i < ilen; ++i) {\n metaData[i] = metaData[i] || me.createMetaData(i);\n }\n\n meta.dataset = meta.dataset || me.createMetaDataset();\n },\n addElementAndReset: function (index) {\n var element = this.createMetaData(index);\n this.getMeta().data.splice(index, 0, element);\n this.updateElement(element, index, true);\n },\n buildOrUpdateElements: function () {\n var me = this;\n var dataset = me.getDataset();\n var data = dataset.data || (dataset.data = []); // In order to correctly handle data addition/deletion animation (an thus simulate\n // real-time charts), we need to monitor these data modifications and synchronize\n // the internal meta data accordingly.\n\n if (me._data !== data) {\n if (me._data) {\n // This case happens when the user replaced the data array instance.\n unlistenArrayEvents(me._data, me);\n }\n\n if (data && Object.isExtensible(data)) {\n listenArrayEvents(data, me);\n }\n\n me._data = data;\n } // Re-sync meta data in case the user replaced the data array or if we missed\n // any updates and so make sure that we handle number of datapoints changing.\n\n\n me.resyncElements();\n },\n\n /**\n * Returns the merged user-supplied and default dataset-level options\n * @private\n */\n _configure: function () {\n var me = this;\n me._config = helpers$1.merge({}, [me.chart.options.datasets[me._type], me.getDataset()], {\n merger: function (key, target, source) {\n if (key !== '_meta' && key !== 'data') {\n helpers$1._merger(key, target, source);\n }\n }\n });\n },\n _update: function (reset) {\n var me = this;\n\n me._configure();\n\n me._cachedDataOpts = null;\n me.update(reset);\n },\n update: helpers$1.noop,\n transition: function (easingValue) {\n var meta = this.getMeta();\n var elements = meta.data || [];\n var ilen = elements.length;\n var i = 0;\n\n for (; i < ilen; ++i) {\n elements[i].transition(easingValue);\n }\n\n if (meta.dataset) {\n meta.dataset.transition(easingValue);\n }\n },\n draw: function () {\n var meta = this.getMeta();\n var elements = meta.data || [];\n var ilen = elements.length;\n var i = 0;\n\n if (meta.dataset) {\n meta.dataset.draw();\n }\n\n for (; i < ilen; ++i) {\n elements[i].draw();\n }\n },\n\n /**\n * Returns a set of predefined style properties that should be used to represent the dataset\n * or the data if the index is specified\n * @param {number} index - data index\n * @return {IStyleInterface} style object\n */\n getStyle: function (index) {\n var me = this;\n var meta = me.getMeta();\n var dataset = meta.dataset;\n var style;\n\n me._configure();\n\n if (dataset && index === undefined) {\n style = me._resolveDatasetElementOptions(dataset || {});\n } else {\n index = index || 0;\n style = me._resolveDataElementOptions(meta.data[index] || {}, index);\n }\n\n if (style.fill === false || style.fill === null) {\n style.backgroundColor = style.borderColor;\n }\n\n return style;\n },\n\n /**\n * @private\n */\n _resolveDatasetElementOptions: function (element, hover) {\n var me = this;\n var chart = me.chart;\n var datasetOpts = me._config;\n var custom = element.custom || {};\n var options = chart.options.elements[me.datasetElementType.prototype._type] || {};\n var elementOptions = me._datasetElementOptions;\n var values = {};\n var i, ilen, key, readKey; // Scriptable options\n\n var context = {\n chart: chart,\n dataset: me.getDataset(),\n datasetIndex: me.index,\n hover: hover\n };\n\n for (i = 0, ilen = elementOptions.length; i < ilen; ++i) {\n key = elementOptions[i];\n readKey = hover ? 'hover' + key.charAt(0).toUpperCase() + key.slice(1) : key;\n values[key] = resolve([custom[readKey], datasetOpts[readKey], options[readKey]], context);\n }\n\n return values;\n },\n\n /**\n * @private\n */\n _resolveDataElementOptions: function (element, index) {\n var me = this;\n var custom = element && element.custom;\n var cached = me._cachedDataOpts;\n\n if (cached && !custom) {\n return cached;\n }\n\n var chart = me.chart;\n var datasetOpts = me._config;\n var options = chart.options.elements[me.dataElementType.prototype._type] || {};\n var elementOptions = me._dataElementOptions;\n var values = {}; // Scriptable options\n\n var context = {\n chart: chart,\n dataIndex: index,\n dataset: me.getDataset(),\n datasetIndex: me.index\n }; // `resolve` sets cacheable to `false` if any option is indexed or scripted\n\n var info = {\n cacheable: !custom\n };\n var keys, i, ilen, key;\n custom = custom || {};\n\n if (helpers$1.isArray(elementOptions)) {\n for (i = 0, ilen = elementOptions.length; i < ilen; ++i) {\n key = elementOptions[i];\n values[key] = resolve([custom[key], datasetOpts[key], options[key]], context, index, info);\n }\n } else {\n keys = Object.keys(elementOptions);\n\n for (i = 0, ilen = keys.length; i < ilen; ++i) {\n key = keys[i];\n values[key] = resolve([custom[key], datasetOpts[elementOptions[key]], datasetOpts[key], options[key]], context, index, info);\n }\n }\n\n if (info.cacheable) {\n me._cachedDataOpts = Object.freeze(values);\n }\n\n return values;\n },\n removeHoverStyle: function (element) {\n helpers$1.merge(element._model, element.$previousStyle || {});\n delete element.$previousStyle;\n },\n setHoverStyle: function (element) {\n var dataset = this.chart.data.datasets[element._datasetIndex];\n var index = element._index;\n var custom = element.custom || {};\n var model = element._model;\n var getHoverColor = helpers$1.getHoverColor;\n element.$previousStyle = {\n backgroundColor: model.backgroundColor,\n borderColor: model.borderColor,\n borderWidth: model.borderWidth\n };\n model.backgroundColor = resolve([custom.hoverBackgroundColor, dataset.hoverBackgroundColor, getHoverColor(model.backgroundColor)], undefined, index);\n model.borderColor = resolve([custom.hoverBorderColor, dataset.hoverBorderColor, getHoverColor(model.borderColor)], undefined, index);\n model.borderWidth = resolve([custom.hoverBorderWidth, dataset.hoverBorderWidth, model.borderWidth], undefined, index);\n },\n\n /**\n * @private\n */\n _removeDatasetHoverStyle: function () {\n var element = this.getMeta().dataset;\n\n if (element) {\n this.removeHoverStyle(element);\n }\n },\n\n /**\n * @private\n */\n _setDatasetHoverStyle: function () {\n var element = this.getMeta().dataset;\n var prev = {};\n var i, ilen, key, keys, hoverOptions, model;\n\n if (!element) {\n return;\n }\n\n model = element._model;\n hoverOptions = this._resolveDatasetElementOptions(element, true);\n keys = Object.keys(hoverOptions);\n\n for (i = 0, ilen = keys.length; i < ilen; ++i) {\n key = keys[i];\n prev[key] = model[key];\n model[key] = hoverOptions[key];\n }\n\n element.$previousStyle = prev;\n },\n\n /**\n * @private\n */\n resyncElements: function () {\n var me = this;\n var meta = me.getMeta();\n var data = me.getDataset().data;\n var numMeta = meta.data.length;\n var numData = data.length;\n\n if (numData < numMeta) {\n meta.data.splice(numData, numMeta - numData);\n } else if (numData > numMeta) {\n me.insertElements(numMeta, numData - numMeta);\n }\n },\n\n /**\n * @private\n */\n insertElements: function (start, count) {\n for (var i = 0; i < count; ++i) {\n this.addElementAndReset(start + i);\n }\n },\n\n /**\n * @private\n */\n onDataPush: function () {\n var count = arguments.length;\n this.insertElements(this.getDataset().data.length - count, count);\n },\n\n /**\n * @private\n */\n onDataPop: function () {\n this.getMeta().data.pop();\n },\n\n /**\n * @private\n */\n onDataShift: function () {\n this.getMeta().data.shift();\n },\n\n /**\n * @private\n */\n onDataSplice: function (start, count) {\n this.getMeta().data.splice(start, count);\n this.insertElements(start, arguments.length - 2);\n },\n\n /**\n * @private\n */\n onDataUnshift: function () {\n this.insertElements(0, arguments.length);\n }\n });\n DatasetController.extend = helpers$1.inherits;\n var core_datasetController = DatasetController;\n var TAU = Math.PI * 2;\n\n core_defaults._set('global', {\n elements: {\n arc: {\n backgroundColor: core_defaults.global.defaultColor,\n borderColor: '#fff',\n borderWidth: 2,\n borderAlign: 'center'\n }\n }\n });\n\n function clipArc(ctx, arc) {\n var startAngle = arc.startAngle;\n var endAngle = arc.endAngle;\n var pixelMargin = arc.pixelMargin;\n var angleMargin = pixelMargin / arc.outerRadius;\n var x = arc.x;\n var y = arc.y; // Draw an inner border by cliping the arc and drawing a double-width border\n // Enlarge the clipping arc by 0.33 pixels to eliminate glitches between borders\n\n ctx.beginPath();\n ctx.arc(x, y, arc.outerRadius, startAngle - angleMargin, endAngle + angleMargin);\n\n if (arc.innerRadius > pixelMargin) {\n angleMargin = pixelMargin / arc.innerRadius;\n ctx.arc(x, y, arc.innerRadius - pixelMargin, endAngle + angleMargin, startAngle - angleMargin, true);\n } else {\n ctx.arc(x, y, pixelMargin, endAngle + Math.PI / 2, startAngle - Math.PI / 2);\n }\n\n ctx.closePath();\n ctx.clip();\n }\n\n function drawFullCircleBorders(ctx, vm, arc, inner) {\n var endAngle = arc.endAngle;\n var i;\n\n if (inner) {\n arc.endAngle = arc.startAngle + TAU;\n clipArc(ctx, arc);\n arc.endAngle = endAngle;\n\n if (arc.endAngle === arc.startAngle && arc.fullCircles) {\n arc.endAngle += TAU;\n arc.fullCircles--;\n }\n }\n\n ctx.beginPath();\n ctx.arc(arc.x, arc.y, arc.innerRadius, arc.startAngle + TAU, arc.startAngle, true);\n\n for (i = 0; i < arc.fullCircles; ++i) {\n ctx.stroke();\n }\n\n ctx.beginPath();\n ctx.arc(arc.x, arc.y, vm.outerRadius, arc.startAngle, arc.startAngle + TAU);\n\n for (i = 0; i < arc.fullCircles; ++i) {\n ctx.stroke();\n }\n }\n\n function drawBorder(ctx, vm, arc) {\n var inner = vm.borderAlign === 'inner';\n\n if (inner) {\n ctx.lineWidth = vm.borderWidth * 2;\n ctx.lineJoin = 'round';\n } else {\n ctx.lineWidth = vm.borderWidth;\n ctx.lineJoin = 'bevel';\n }\n\n if (arc.fullCircles) {\n drawFullCircleBorders(ctx, vm, arc, inner);\n }\n\n if (inner) {\n clipArc(ctx, arc);\n }\n\n ctx.beginPath();\n ctx.arc(arc.x, arc.y, vm.outerRadius, arc.startAngle, arc.endAngle);\n ctx.arc(arc.x, arc.y, arc.innerRadius, arc.endAngle, arc.startAngle, true);\n ctx.closePath();\n ctx.stroke();\n }\n\n var element_arc = core_element.extend({\n _type: 'arc',\n inLabelRange: function (mouseX) {\n var vm = this._view;\n\n if (vm) {\n return Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2);\n }\n\n return false;\n },\n inRange: function (chartX, chartY) {\n var vm = this._view;\n\n if (vm) {\n var pointRelativePosition = helpers$1.getAngleFromPoint(vm, {\n x: chartX,\n y: chartY\n });\n var angle = pointRelativePosition.angle;\n var distance = pointRelativePosition.distance; // Sanitise angle range\n\n var startAngle = vm.startAngle;\n var endAngle = vm.endAngle;\n\n while (endAngle < startAngle) {\n endAngle += TAU;\n }\n\n while (angle > endAngle) {\n angle -= TAU;\n }\n\n while (angle < startAngle) {\n angle += TAU;\n } // Check if within the range of the open/close angle\n\n\n var betweenAngles = angle >= startAngle && angle <= endAngle;\n var withinRadius = distance >= vm.innerRadius && distance <= vm.outerRadius;\n return betweenAngles && withinRadius;\n }\n\n return false;\n },\n getCenterPoint: function () {\n var vm = this._view;\n var halfAngle = (vm.startAngle + vm.endAngle) / 2;\n var halfRadius = (vm.innerRadius + vm.outerRadius) / 2;\n return {\n x: vm.x + Math.cos(halfAngle) * halfRadius,\n y: vm.y + Math.sin(halfAngle) * halfRadius\n };\n },\n getArea: function () {\n var vm = this._view;\n return Math.PI * ((vm.endAngle - vm.startAngle) / (2 * Math.PI)) * (Math.pow(vm.outerRadius, 2) - Math.pow(vm.innerRadius, 2));\n },\n tooltipPosition: function () {\n var vm = this._view;\n var centreAngle = vm.startAngle + (vm.endAngle - vm.startAngle) / 2;\n var rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius;\n return {\n x: vm.x + Math.cos(centreAngle) * rangeFromCentre,\n y: vm.y + Math.sin(centreAngle) * rangeFromCentre\n };\n },\n draw: function () {\n var ctx = this._chart.ctx;\n var vm = this._view;\n var pixelMargin = vm.borderAlign === 'inner' ? 0.33 : 0;\n var arc = {\n x: vm.x,\n y: vm.y,\n innerRadius: vm.innerRadius,\n outerRadius: Math.max(vm.outerRadius - pixelMargin, 0),\n pixelMargin: pixelMargin,\n startAngle: vm.startAngle,\n endAngle: vm.endAngle,\n fullCircles: Math.floor(vm.circumference / TAU)\n };\n var i;\n ctx.save();\n ctx.fillStyle = vm.backgroundColor;\n ctx.strokeStyle = vm.borderColor;\n\n if (arc.fullCircles) {\n arc.endAngle = arc.startAngle + TAU;\n ctx.beginPath();\n ctx.arc(arc.x, arc.y, arc.outerRadius, arc.startAngle, arc.endAngle);\n ctx.arc(arc.x, arc.y, arc.innerRadius, arc.endAngle, arc.startAngle, true);\n ctx.closePath();\n\n for (i = 0; i < arc.fullCircles; ++i) {\n ctx.fill();\n }\n\n arc.endAngle = arc.startAngle + vm.circumference % TAU;\n }\n\n ctx.beginPath();\n ctx.arc(arc.x, arc.y, arc.outerRadius, arc.startAngle, arc.endAngle);\n ctx.arc(arc.x, arc.y, arc.innerRadius, arc.endAngle, arc.startAngle, true);\n ctx.closePath();\n ctx.fill();\n\n if (vm.borderWidth) {\n drawBorder(ctx, vm, arc);\n }\n\n ctx.restore();\n }\n });\n var valueOrDefault$1 = helpers$1.valueOrDefault;\n var defaultColor = core_defaults.global.defaultColor;\n\n core_defaults._set('global', {\n elements: {\n line: {\n tension: 0.4,\n backgroundColor: defaultColor,\n borderWidth: 3,\n borderColor: defaultColor,\n borderCapStyle: 'butt',\n borderDash: [],\n borderDashOffset: 0.0,\n borderJoinStyle: 'miter',\n capBezierPoints: true,\n fill: true // do we fill in the area between the line and its base axis\n\n }\n }\n });\n\n var element_line = core_element.extend({\n _type: 'line',\n draw: function () {\n var me = this;\n var vm = me._view;\n var ctx = me._chart.ctx;\n var spanGaps = vm.spanGaps;\n\n var points = me._children.slice(); // clone array\n\n\n var globalDefaults = core_defaults.global;\n var globalOptionLineElements = globalDefaults.elements.line;\n var lastDrawnIndex = -1;\n var closePath = me._loop;\n var index, previous, currentVM;\n\n if (!points.length) {\n return;\n }\n\n if (me._loop) {\n for (index = 0; index < points.length; ++index) {\n previous = helpers$1.previousItem(points, index); // If the line has an open path, shift the point array\n\n if (!points[index]._view.skip && previous._view.skip) {\n points = points.slice(index).concat(points.slice(0, index));\n closePath = spanGaps;\n break;\n }\n } // If the line has a close path, add the first point again\n\n\n if (closePath) {\n points.push(points[0]);\n }\n }\n\n ctx.save(); // Stroke Line Options\n\n ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle; // IE 9 and 10 do not support line dash\n\n if (ctx.setLineDash) {\n ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash);\n }\n\n ctx.lineDashOffset = valueOrDefault$1(vm.borderDashOffset, globalOptionLineElements.borderDashOffset);\n ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;\n ctx.lineWidth = valueOrDefault$1(vm.borderWidth, globalOptionLineElements.borderWidth);\n ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor; // Stroke Line\n\n ctx.beginPath(); // First point moves to it's starting position no matter what\n\n currentVM = points[0]._view;\n\n if (!currentVM.skip) {\n ctx.moveTo(currentVM.x, currentVM.y);\n lastDrawnIndex = 0;\n }\n\n for (index = 1; index < points.length; ++index) {\n currentVM = points[index]._view;\n previous = lastDrawnIndex === -1 ? helpers$1.previousItem(points, index) : points[lastDrawnIndex];\n\n if (!currentVM.skip) {\n if (lastDrawnIndex !== index - 1 && !spanGaps || lastDrawnIndex === -1) {\n // There was a gap and this is the first point after the gap\n ctx.moveTo(currentVM.x, currentVM.y);\n } else {\n // Line to next point\n helpers$1.canvas.lineTo(ctx, previous._view, currentVM);\n }\n\n lastDrawnIndex = index;\n }\n }\n\n if (closePath) {\n ctx.closePath();\n }\n\n ctx.stroke();\n ctx.restore();\n }\n });\n var valueOrDefault$2 = helpers$1.valueOrDefault;\n var defaultColor$1 = core_defaults.global.defaultColor;\n\n core_defaults._set('global', {\n elements: {\n point: {\n radius: 3,\n pointStyle: 'circle',\n backgroundColor: defaultColor$1,\n borderColor: defaultColor$1,\n borderWidth: 1,\n // Hover\n hitRadius: 1,\n hoverRadius: 4,\n hoverBorderWidth: 1\n }\n }\n });\n\n function xRange(mouseX) {\n var vm = this._view;\n return vm ? Math.abs(mouseX - vm.x) < vm.radius + vm.hitRadius : false;\n }\n\n function yRange(mouseY) {\n var vm = this._view;\n return vm ? Math.abs(mouseY - vm.y) < vm.radius + vm.hitRadius : false;\n }\n\n var element_point = core_element.extend({\n _type: 'point',\n inRange: function (mouseX, mouseY) {\n var vm = this._view;\n return vm ? Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2) < Math.pow(vm.hitRadius + vm.radius, 2) : false;\n },\n inLabelRange: xRange,\n inXRange: xRange,\n inYRange: yRange,\n getCenterPoint: function () {\n var vm = this._view;\n return {\n x: vm.x,\n y: vm.y\n };\n },\n getArea: function () {\n return Math.PI * Math.pow(this._view.radius, 2);\n },\n tooltipPosition: function () {\n var vm = this._view;\n return {\n x: vm.x,\n y: vm.y,\n padding: vm.radius + vm.borderWidth\n };\n },\n draw: function (chartArea) {\n var vm = this._view;\n var ctx = this._chart.ctx;\n var pointStyle = vm.pointStyle;\n var rotation = vm.rotation;\n var radius = vm.radius;\n var x = vm.x;\n var y = vm.y;\n var globalDefaults = core_defaults.global;\n var defaultColor = globalDefaults.defaultColor; // eslint-disable-line no-shadow\n\n if (vm.skip) {\n return;\n } // Clipping for Points.\n\n\n if (chartArea === undefined || helpers$1.canvas._isPointInArea(vm, chartArea)) {\n ctx.strokeStyle = vm.borderColor || defaultColor;\n ctx.lineWidth = valueOrDefault$2(vm.borderWidth, globalDefaults.elements.point.borderWidth);\n ctx.fillStyle = vm.backgroundColor || defaultColor;\n helpers$1.canvas.drawPoint(ctx, pointStyle, radius, x, y, rotation);\n }\n }\n });\n var defaultColor$2 = core_defaults.global.defaultColor;\n\n core_defaults._set('global', {\n elements: {\n rectangle: {\n backgroundColor: defaultColor$2,\n borderColor: defaultColor$2,\n borderSkipped: 'bottom',\n borderWidth: 0\n }\n }\n });\n\n function isVertical(vm) {\n return vm && vm.width !== undefined;\n }\n /**\n * Helper function to get the bounds of the bar regardless of the orientation\n * @param bar {Chart.Element.Rectangle} the bar\n * @return {Bounds} bounds of the bar\n * @private\n */\n\n\n function getBarBounds(vm) {\n var x1, x2, y1, y2, half;\n\n if (isVertical(vm)) {\n half = vm.width / 2;\n x1 = vm.x - half;\n x2 = vm.x + half;\n y1 = Math.min(vm.y, vm.base);\n y2 = Math.max(vm.y, vm.base);\n } else {\n half = vm.height / 2;\n x1 = Math.min(vm.x, vm.base);\n x2 = Math.max(vm.x, vm.base);\n y1 = vm.y - half;\n y2 = vm.y + half;\n }\n\n return {\n left: x1,\n top: y1,\n right: x2,\n bottom: y2\n };\n }\n\n function swap(orig, v1, v2) {\n return orig === v1 ? v2 : orig === v2 ? v1 : orig;\n }\n\n function parseBorderSkipped(vm) {\n var edge = vm.borderSkipped;\n var res = {};\n\n if (!edge) {\n return res;\n }\n\n if (vm.horizontal) {\n if (vm.base > vm.x) {\n edge = swap(edge, 'left', 'right');\n }\n } else if (vm.base < vm.y) {\n edge = swap(edge, 'bottom', 'top');\n }\n\n res[edge] = true;\n return res;\n }\n\n function parseBorderWidth(vm, maxW, maxH) {\n var value = vm.borderWidth;\n var skip = parseBorderSkipped(vm);\n var t, r, b, l;\n\n if (helpers$1.isObject(value)) {\n t = +value.top || 0;\n r = +value.right || 0;\n b = +value.bottom || 0;\n l = +value.left || 0;\n } else {\n t = r = b = l = +value || 0;\n }\n\n return {\n t: skip.top || t < 0 ? 0 : t > maxH ? maxH : t,\n r: skip.right || r < 0 ? 0 : r > maxW ? maxW : r,\n b: skip.bottom || b < 0 ? 0 : b > maxH ? maxH : b,\n l: skip.left || l < 0 ? 0 : l > maxW ? maxW : l\n };\n }\n\n function boundingRects(vm) {\n var bounds = getBarBounds(vm);\n var width = bounds.right - bounds.left;\n var height = bounds.bottom - bounds.top;\n var border = parseBorderWidth(vm, width / 2, height / 2);\n return {\n outer: {\n x: bounds.left,\n y: bounds.top,\n w: width,\n h: height\n },\n inner: {\n x: bounds.left + border.l,\n y: bounds.top + border.t,\n w: width - border.l - border.r,\n h: height - border.t - border.b\n }\n };\n }\n\n function inRange(vm, x, y) {\n var skipX = x === null;\n var skipY = y === null;\n var bounds = !vm || skipX && skipY ? false : getBarBounds(vm);\n return bounds && (skipX || x >= bounds.left && x <= bounds.right) && (skipY || y >= bounds.top && y <= bounds.bottom);\n }\n\n var element_rectangle = core_element.extend({\n _type: 'rectangle',\n draw: function () {\n var ctx = this._chart.ctx;\n var vm = this._view;\n var rects = boundingRects(vm);\n var outer = rects.outer;\n var inner = rects.inner;\n ctx.fillStyle = vm.backgroundColor;\n ctx.fillRect(outer.x, outer.y, outer.w, outer.h);\n\n if (outer.w === inner.w && outer.h === inner.h) {\n return;\n }\n\n ctx.save();\n ctx.beginPath();\n ctx.rect(outer.x, outer.y, outer.w, outer.h);\n ctx.clip();\n ctx.fillStyle = vm.borderColor;\n ctx.rect(inner.x, inner.y, inner.w, inner.h);\n ctx.fill('evenodd');\n ctx.restore();\n },\n height: function () {\n var vm = this._view;\n return vm.base - vm.y;\n },\n inRange: function (mouseX, mouseY) {\n return inRange(this._view, mouseX, mouseY);\n },\n inLabelRange: function (mouseX, mouseY) {\n var vm = this._view;\n return isVertical(vm) ? inRange(vm, mouseX, null) : inRange(vm, null, mouseY);\n },\n inXRange: function (mouseX) {\n return inRange(this._view, mouseX, null);\n },\n inYRange: function (mouseY) {\n return inRange(this._view, null, mouseY);\n },\n getCenterPoint: function () {\n var vm = this._view;\n var x, y;\n\n if (isVertical(vm)) {\n x = vm.x;\n y = (vm.y + vm.base) / 2;\n } else {\n x = (vm.x + vm.base) / 2;\n y = vm.y;\n }\n\n return {\n x: x,\n y: y\n };\n },\n getArea: function () {\n var vm = this._view;\n return isVertical(vm) ? vm.width * Math.abs(vm.y - vm.base) : vm.height * Math.abs(vm.x - vm.base);\n },\n tooltipPosition: function () {\n var vm = this._view;\n return {\n x: vm.x,\n y: vm.y\n };\n }\n });\n var elements = {};\n var Arc = element_arc;\n var Line = element_line;\n var Point = element_point;\n var Rectangle = element_rectangle;\n elements.Arc = Arc;\n elements.Line = Line;\n elements.Point = Point;\n elements.Rectangle = Rectangle;\n var deprecated = helpers$1._deprecated;\n var valueOrDefault$3 = helpers$1.valueOrDefault;\n\n core_defaults._set('bar', {\n hover: {\n mode: 'label'\n },\n scales: {\n xAxes: [{\n type: 'category',\n offset: true,\n gridLines: {\n offsetGridLines: true\n }\n }],\n yAxes: [{\n type: 'linear'\n }]\n }\n });\n\n core_defaults._set('global', {\n datasets: {\n bar: {\n categoryPercentage: 0.8,\n barPercentage: 0.9\n }\n }\n });\n /**\n * Computes the \"optimal\" sample size to maintain bars equally sized while preventing overlap.\n * @private\n */\n\n\n function computeMinSampleSize(scale, pixels) {\n var min = scale._length;\n var prev, curr, i, ilen;\n\n for (i = 1, ilen = pixels.length; i < ilen; ++i) {\n min = Math.min(min, Math.abs(pixels[i] - pixels[i - 1]));\n }\n\n for (i = 0, ilen = scale.getTicks().length; i < ilen; ++i) {\n curr = scale.getPixelForTick(i);\n min = i > 0 ? Math.min(min, Math.abs(curr - prev)) : min;\n prev = curr;\n }\n\n return min;\n }\n /**\n * Computes an \"ideal\" category based on the absolute bar thickness or, if undefined or null,\n * uses the smallest interval (see computeMinSampleSize) that prevents bar overlapping. This\n * mode currently always generates bars equally sized (until we introduce scriptable options?).\n * @private\n */\n\n\n function computeFitCategoryTraits(index, ruler, options) {\n var thickness = options.barThickness;\n var count = ruler.stackCount;\n var curr = ruler.pixels[index];\n var min = helpers$1.isNullOrUndef(thickness) ? computeMinSampleSize(ruler.scale, ruler.pixels) : -1;\n var size, ratio;\n\n if (helpers$1.isNullOrUndef(thickness)) {\n size = min * options.categoryPercentage;\n ratio = options.barPercentage;\n } else {\n // When bar thickness is enforced, category and bar percentages are ignored.\n // Note(SB): we could add support for relative bar thickness (e.g. barThickness: '50%')\n // and deprecate barPercentage since this value is ignored when thickness is absolute.\n size = thickness * count;\n ratio = 1;\n }\n\n return {\n chunk: size / count,\n ratio: ratio,\n start: curr - size / 2\n };\n }\n /**\n * Computes an \"optimal\" category that globally arranges bars side by side (no gap when\n * percentage options are 1), based on the previous and following categories. This mode\n * generates bars with different widths when data are not evenly spaced.\n * @private\n */\n\n\n function computeFlexCategoryTraits(index, ruler, options) {\n var pixels = ruler.pixels;\n var curr = pixels[index];\n var prev = index > 0 ? pixels[index - 1] : null;\n var next = index < pixels.length - 1 ? pixels[index + 1] : null;\n var percent = options.categoryPercentage;\n var start, size;\n\n if (prev === null) {\n // first data: its size is double based on the next point or,\n // if it's also the last data, we use the scale size.\n prev = curr - (next === null ? ruler.end - ruler.start : next - curr);\n }\n\n if (next === null) {\n // last data: its size is also double based on the previous point.\n next = curr + curr - prev;\n }\n\n start = curr - (curr - Math.min(prev, next)) / 2 * percent;\n size = Math.abs(next - prev) / 2 * percent;\n return {\n chunk: size / ruler.stackCount,\n ratio: options.barPercentage,\n start: start\n };\n }\n\n var controller_bar = core_datasetController.extend({\n dataElementType: elements.Rectangle,\n\n /**\n * @private\n */\n _dataElementOptions: ['backgroundColor', 'borderColor', 'borderSkipped', 'borderWidth', 'barPercentage', 'barThickness', 'categoryPercentage', 'maxBarThickness', 'minBarLength'],\n initialize: function () {\n var me = this;\n var meta, scaleOpts;\n core_datasetController.prototype.initialize.apply(me, arguments);\n meta = me.getMeta();\n meta.stack = me.getDataset().stack;\n meta.bar = true;\n scaleOpts = me._getIndexScale().options;\n deprecated('bar chart', scaleOpts.barPercentage, 'scales.[x/y]Axes.barPercentage', 'dataset.barPercentage');\n deprecated('bar chart', scaleOpts.barThickness, 'scales.[x/y]Axes.barThickness', 'dataset.barThickness');\n deprecated('bar chart', scaleOpts.categoryPercentage, 'scales.[x/y]Axes.categoryPercentage', 'dataset.categoryPercentage');\n deprecated('bar chart', me._getValueScale().options.minBarLength, 'scales.[x/y]Axes.minBarLength', 'dataset.minBarLength');\n deprecated('bar chart', scaleOpts.maxBarThickness, 'scales.[x/y]Axes.maxBarThickness', 'dataset.maxBarThickness');\n },\n update: function (reset) {\n var me = this;\n var rects = me.getMeta().data;\n var i, ilen;\n me._ruler = me.getRuler();\n\n for (i = 0, ilen = rects.length; i < ilen; ++i) {\n me.updateElement(rects[i], i, reset);\n }\n },\n updateElement: function (rectangle, index, reset) {\n var me = this;\n var meta = me.getMeta();\n var dataset = me.getDataset();\n\n var options = me._resolveDataElementOptions(rectangle, index);\n\n rectangle._xScale = me.getScaleForId(meta.xAxisID);\n rectangle._yScale = me.getScaleForId(meta.yAxisID);\n rectangle._datasetIndex = me.index;\n rectangle._index = index;\n rectangle._model = {\n backgroundColor: options.backgroundColor,\n borderColor: options.borderColor,\n borderSkipped: options.borderSkipped,\n borderWidth: options.borderWidth,\n datasetLabel: dataset.label,\n label: me.chart.data.labels[index]\n };\n\n if (helpers$1.isArray(dataset.data[index])) {\n rectangle._model.borderSkipped = null;\n }\n\n me._updateElementGeometry(rectangle, index, reset, options);\n\n rectangle.pivot();\n },\n\n /**\n * @private\n */\n _updateElementGeometry: function (rectangle, index, reset, options) {\n var me = this;\n var model = rectangle._model;\n\n var vscale = me._getValueScale();\n\n var base = vscale.getBasePixel();\n var horizontal = vscale.isHorizontal();\n var ruler = me._ruler || me.getRuler();\n var vpixels = me.calculateBarValuePixels(me.index, index, options);\n var ipixels = me.calculateBarIndexPixels(me.index, index, ruler, options);\n model.horizontal = horizontal;\n model.base = reset ? base : vpixels.base;\n model.x = horizontal ? reset ? base : vpixels.head : ipixels.center;\n model.y = horizontal ? ipixels.center : reset ? base : vpixels.head;\n model.height = horizontal ? ipixels.size : undefined;\n model.width = horizontal ? undefined : ipixels.size;\n },\n\n /**\n * Returns the stacks based on groups and bar visibility.\n * @param {number} [last] - The dataset index\n * @returns {string[]} The list of stack IDs\n * @private\n */\n _getStacks: function (last) {\n var me = this;\n\n var scale = me._getIndexScale();\n\n var metasets = scale._getMatchingVisibleMetas(me._type);\n\n var stacked = scale.options.stacked;\n var ilen = metasets.length;\n var stacks = [];\n var i, meta;\n\n for (i = 0; i < ilen; ++i) {\n meta = metasets[i]; // stacked | meta.stack\n // | found | not found | undefined\n // false | x | x | x\n // true | | x |\n // undefined | | x | x\n\n if (stacked === false || stacks.indexOf(meta.stack) === -1 || stacked === undefined && meta.stack === undefined) {\n stacks.push(meta.stack);\n }\n\n if (meta.index === last) {\n break;\n }\n }\n\n return stacks;\n },\n\n /**\n * Returns the effective number of stacks based on groups and bar visibility.\n * @private\n */\n getStackCount: function () {\n return this._getStacks().length;\n },\n\n /**\n * Returns the stack index for the given dataset based on groups and bar visibility.\n * @param {number} [datasetIndex] - The dataset index\n * @param {string} [name] - The stack name to find\n * @returns {number} The stack index\n * @private\n */\n getStackIndex: function (datasetIndex, name) {\n var stacks = this._getStacks(datasetIndex);\n\n var index = name !== undefined ? stacks.indexOf(name) : -1; // indexOf returns -1 if element is not present\n\n return index === -1 ? stacks.length - 1 : index;\n },\n\n /**\n * @private\n */\n getRuler: function () {\n var me = this;\n\n var scale = me._getIndexScale();\n\n var pixels = [];\n var i, ilen;\n\n for (i = 0, ilen = me.getMeta().data.length; i < ilen; ++i) {\n pixels.push(scale.getPixelForValue(null, i, me.index));\n }\n\n return {\n pixels: pixels,\n start: scale._startPixel,\n end: scale._endPixel,\n stackCount: me.getStackCount(),\n scale: scale\n };\n },\n\n /**\n * Note: pixel values are not clamped to the scale area.\n * @private\n */\n calculateBarValuePixels: function (datasetIndex, index, options) {\n var me = this;\n var chart = me.chart;\n\n var scale = me._getValueScale();\n\n var isHorizontal = scale.isHorizontal();\n var datasets = chart.data.datasets;\n\n var metasets = scale._getMatchingVisibleMetas(me._type);\n\n var value = scale._parseValue(datasets[datasetIndex].data[index]);\n\n var minBarLength = options.minBarLength;\n var stacked = scale.options.stacked;\n var stack = me.getMeta().stack;\n var start = value.start === undefined ? 0 : value.max >= 0 && value.min >= 0 ? value.min : value.max;\n var length = value.start === undefined ? value.end : value.max >= 0 && value.min >= 0 ? value.max - value.min : value.min - value.max;\n var ilen = metasets.length;\n var i, imeta, ivalue, base, head, size, stackLength;\n\n if (stacked || stacked === undefined && stack !== undefined) {\n for (i = 0; i < ilen; ++i) {\n imeta = metasets[i];\n\n if (imeta.index === datasetIndex) {\n break;\n }\n\n if (imeta.stack === stack) {\n stackLength = scale._parseValue(datasets[imeta.index].data[index]);\n ivalue = stackLength.start === undefined ? stackLength.end : stackLength.min >= 0 && stackLength.max >= 0 ? stackLength.max : stackLength.min;\n\n if (value.min < 0 && ivalue < 0 || value.max >= 0 && ivalue > 0) {\n start += ivalue;\n }\n }\n }\n }\n\n base = scale.getPixelForValue(start);\n head = scale.getPixelForValue(start + length);\n size = head - base;\n\n if (minBarLength !== undefined && Math.abs(size) < minBarLength) {\n size = minBarLength;\n\n if (length >= 0 && !isHorizontal || length < 0 && isHorizontal) {\n head = base - minBarLength;\n } else {\n head = base + minBarLength;\n }\n }\n\n return {\n size: size,\n base: base,\n head: head,\n center: head + size / 2\n };\n },\n\n /**\n * @private\n */\n calculateBarIndexPixels: function (datasetIndex, index, ruler, options) {\n var me = this;\n var range = options.barThickness === 'flex' ? computeFlexCategoryTraits(index, ruler, options) : computeFitCategoryTraits(index, ruler, options);\n var stackIndex = me.getStackIndex(datasetIndex, me.getMeta().stack);\n var center = range.start + range.chunk * stackIndex + range.chunk / 2;\n var size = Math.min(valueOrDefault$3(options.maxBarThickness, Infinity), range.chunk * range.ratio);\n return {\n base: center - size / 2,\n head: center + size / 2,\n center: center,\n size: size\n };\n },\n draw: function () {\n var me = this;\n var chart = me.chart;\n\n var scale = me._getValueScale();\n\n var rects = me.getMeta().data;\n var dataset = me.getDataset();\n var ilen = rects.length;\n var i = 0;\n helpers$1.canvas.clipArea(chart.ctx, chart.chartArea);\n\n for (; i < ilen; ++i) {\n var val = scale._parseValue(dataset.data[i]);\n\n if (!isNaN(val.min) && !isNaN(val.max)) {\n rects[i].draw();\n }\n }\n\n helpers$1.canvas.unclipArea(chart.ctx);\n },\n\n /**\n * @private\n */\n _resolveDataElementOptions: function () {\n var me = this;\n var values = helpers$1.extend({}, core_datasetController.prototype._resolveDataElementOptions.apply(me, arguments));\n\n var indexOpts = me._getIndexScale().options;\n\n var valueOpts = me._getValueScale().options;\n\n values.barPercentage = valueOrDefault$3(indexOpts.barPercentage, values.barPercentage);\n values.barThickness = valueOrDefault$3(indexOpts.barThickness, values.barThickness);\n values.categoryPercentage = valueOrDefault$3(indexOpts.categoryPercentage, values.categoryPercentage);\n values.maxBarThickness = valueOrDefault$3(indexOpts.maxBarThickness, values.maxBarThickness);\n values.minBarLength = valueOrDefault$3(valueOpts.minBarLength, values.minBarLength);\n return values;\n }\n });\n var valueOrDefault$4 = helpers$1.valueOrDefault;\n var resolve$1 = helpers$1.options.resolve;\n\n core_defaults._set('bubble', {\n hover: {\n mode: 'single'\n },\n scales: {\n xAxes: [{\n type: 'linear',\n // bubble should probably use a linear scale by default\n position: 'bottom',\n id: 'x-axis-0' // need an ID so datasets can reference the scale\n\n }],\n yAxes: [{\n type: 'linear',\n position: 'left',\n id: 'y-axis-0'\n }]\n },\n tooltips: {\n callbacks: {\n title: function () {\n // Title doesn't make sense for scatter since we format the data as a point\n return '';\n },\n label: function (item, data) {\n var datasetLabel = data.datasets[item.datasetIndex].label || '';\n var dataPoint = data.datasets[item.datasetIndex].data[item.index];\n return datasetLabel + ': (' + item.xLabel + ', ' + item.yLabel + ', ' + dataPoint.r + ')';\n }\n }\n }\n });\n\n var controller_bubble = core_datasetController.extend({\n /**\n * @protected\n */\n dataElementType: elements.Point,\n\n /**\n * @private\n */\n _dataElementOptions: ['backgroundColor', 'borderColor', 'borderWidth', 'hoverBackgroundColor', 'hoverBorderColor', 'hoverBorderWidth', 'hoverRadius', 'hitRadius', 'pointStyle', 'rotation'],\n\n /**\n * @protected\n */\n update: function (reset) {\n var me = this;\n var meta = me.getMeta();\n var points = meta.data; // Update Points\n\n helpers$1.each(points, function (point, index) {\n me.updateElement(point, index, reset);\n });\n },\n\n /**\n * @protected\n */\n updateElement: function (point, index, reset) {\n var me = this;\n var meta = me.getMeta();\n var custom = point.custom || {};\n var xScale = me.getScaleForId(meta.xAxisID);\n var yScale = me.getScaleForId(meta.yAxisID);\n\n var options = me._resolveDataElementOptions(point, index);\n\n var data = me.getDataset().data[index];\n var dsIndex = me.index;\n var x = reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 'object' ? data : NaN, index, dsIndex);\n var y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex);\n point._xScale = xScale;\n point._yScale = yScale;\n point._options = options;\n point._datasetIndex = dsIndex;\n point._index = index;\n point._model = {\n backgroundColor: options.backgroundColor,\n borderColor: options.borderColor,\n borderWidth: options.borderWidth,\n hitRadius: options.hitRadius,\n pointStyle: options.pointStyle,\n rotation: options.rotation,\n radius: reset ? 0 : options.radius,\n skip: custom.skip || isNaN(x) || isNaN(y),\n x: x,\n y: y\n };\n point.pivot();\n },\n\n /**\n * @protected\n */\n setHoverStyle: function (point) {\n var model = point._model;\n var options = point._options;\n var getHoverColor = helpers$1.getHoverColor;\n point.$previousStyle = {\n backgroundColor: model.backgroundColor,\n borderColor: model.borderColor,\n borderWidth: model.borderWidth,\n radius: model.radius\n };\n model.backgroundColor = valueOrDefault$4(options.hoverBackgroundColor, getHoverColor(options.backgroundColor));\n model.borderColor = valueOrDefault$4(options.hoverBorderColor, getHoverColor(options.borderColor));\n model.borderWidth = valueOrDefault$4(options.hoverBorderWidth, options.borderWidth);\n model.radius = options.radius + options.hoverRadius;\n },\n\n /**\n * @private\n */\n _resolveDataElementOptions: function (point, index) {\n var me = this;\n var chart = me.chart;\n var dataset = me.getDataset();\n var custom = point.custom || {};\n var data = dataset.data[index] || {};\n\n var values = core_datasetController.prototype._resolveDataElementOptions.apply(me, arguments); // Scriptable options\n\n\n var context = {\n chart: chart,\n dataIndex: index,\n dataset: dataset,\n datasetIndex: me.index\n }; // In case values were cached (and thus frozen), we need to clone the values\n\n if (me._cachedDataOpts === values) {\n values = helpers$1.extend({}, values);\n } // Custom radius resolution\n\n\n values.radius = resolve$1([custom.radius, data.r, me._config.radius, chart.options.elements.point.radius], context, index);\n return values;\n }\n });\n var valueOrDefault$5 = helpers$1.valueOrDefault;\n var PI$1 = Math.PI;\n var DOUBLE_PI$1 = PI$1 * 2;\n var HALF_PI$1 = PI$1 / 2;\n\n core_defaults._set('doughnut', {\n animation: {\n // Boolean - Whether we animate the rotation of the Doughnut\n animateRotate: true,\n // Boolean - Whether we animate scaling the Doughnut from the centre\n animateScale: false\n },\n hover: {\n mode: 'single'\n },\n legendCallback: function (chart) {\n var list = document.createElement('ul');\n var data = chart.data;\n var datasets = data.datasets;\n var labels = data.labels;\n var i, ilen, listItem, listItemSpan;\n list.setAttribute('class', chart.id + '-legend');\n\n if (datasets.length) {\n for (i = 0, ilen = datasets[0].data.length; i < ilen; ++i) {\n listItem = list.appendChild(document.createElement('li'));\n listItemSpan = listItem.appendChild(document.createElement('span'));\n listItemSpan.style.backgroundColor = datasets[0].backgroundColor[i];\n\n if (labels[i]) {\n listItem.appendChild(document.createTextNode(labels[i]));\n }\n }\n }\n\n return list.outerHTML;\n },\n legend: {\n labels: {\n generateLabels: function (chart) {\n var data = chart.data;\n\n if (data.labels.length && data.datasets.length) {\n return data.labels.map(function (label, i) {\n var meta = chart.getDatasetMeta(0);\n var style = meta.controller.getStyle(i);\n return {\n text: label,\n fillStyle: style.backgroundColor,\n strokeStyle: style.borderColor,\n lineWidth: style.borderWidth,\n hidden: isNaN(data.datasets[0].data[i]) || meta.data[i].hidden,\n // Extra data used for toggling the correct item\n index: i\n };\n });\n }\n\n return [];\n }\n },\n onClick: function (e, legendItem) {\n var index = legendItem.index;\n var chart = this.chart;\n var i, ilen, meta;\n\n for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {\n meta = chart.getDatasetMeta(i); // toggle visibility of index if exists\n\n if (meta.data[index]) {\n meta.data[index].hidden = !meta.data[index].hidden;\n }\n }\n\n chart.update();\n }\n },\n // The percentage of the chart that we cut out of the middle.\n cutoutPercentage: 50,\n // The rotation of the chart, where the first data arc begins.\n rotation: -HALF_PI$1,\n // The total circumference of the chart.\n circumference: DOUBLE_PI$1,\n // Need to override these to give a nice default\n tooltips: {\n callbacks: {\n title: function () {\n return '';\n },\n label: function (tooltipItem, data) {\n var dataLabel = data.labels[tooltipItem.index];\n var value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\n\n if (helpers$1.isArray(dataLabel)) {\n // show value on first line of multiline label\n // need to clone because we are changing the value\n dataLabel = dataLabel.slice();\n dataLabel[0] += value;\n } else {\n dataLabel += value;\n }\n\n return dataLabel;\n }\n }\n }\n });\n\n var controller_doughnut = core_datasetController.extend({\n dataElementType: elements.Arc,\n linkScales: helpers$1.noop,\n\n /**\n * @private\n */\n _dataElementOptions: ['backgroundColor', 'borderColor', 'borderWidth', 'borderAlign', 'hoverBackgroundColor', 'hoverBorderColor', 'hoverBorderWidth'],\n // Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly\n getRingIndex: function (datasetIndex) {\n var ringIndex = 0;\n\n for (var j = 0; j < datasetIndex; ++j) {\n if (this.chart.isDatasetVisible(j)) {\n ++ringIndex;\n }\n }\n\n return ringIndex;\n },\n update: function (reset) {\n var me = this;\n var chart = me.chart;\n var chartArea = chart.chartArea;\n var opts = chart.options;\n var ratioX = 1;\n var ratioY = 1;\n var offsetX = 0;\n var offsetY = 0;\n var meta = me.getMeta();\n var arcs = meta.data;\n var cutout = opts.cutoutPercentage / 100 || 0;\n var circumference = opts.circumference;\n\n var chartWeight = me._getRingWeight(me.index);\n\n var maxWidth, maxHeight, i, ilen; // If the chart's circumference isn't a full circle, calculate size as a ratio of the width/height of the arc\n\n if (circumference < DOUBLE_PI$1) {\n var startAngle = opts.rotation % DOUBLE_PI$1;\n startAngle += startAngle >= PI$1 ? -DOUBLE_PI$1 : startAngle < -PI$1 ? DOUBLE_PI$1 : 0;\n var endAngle = startAngle + circumference;\n var startX = Math.cos(startAngle);\n var startY = Math.sin(startAngle);\n var endX = Math.cos(endAngle);\n var endY = Math.sin(endAngle);\n var contains0 = startAngle <= 0 && endAngle >= 0 || endAngle >= DOUBLE_PI$1;\n var contains90 = startAngle <= HALF_PI$1 && endAngle >= HALF_PI$1 || endAngle >= DOUBLE_PI$1 + HALF_PI$1;\n var contains180 = startAngle === -PI$1 || endAngle >= PI$1;\n var contains270 = startAngle <= -HALF_PI$1 && endAngle >= -HALF_PI$1 || endAngle >= PI$1 + HALF_PI$1;\n var minX = contains180 ? -1 : Math.min(startX, startX * cutout, endX, endX * cutout);\n var minY = contains270 ? -1 : Math.min(startY, startY * cutout, endY, endY * cutout);\n var maxX = contains0 ? 1 : Math.max(startX, startX * cutout, endX, endX * cutout);\n var maxY = contains90 ? 1 : Math.max(startY, startY * cutout, endY, endY * cutout);\n ratioX = (maxX - minX) / 2;\n ratioY = (maxY - minY) / 2;\n offsetX = -(maxX + minX) / 2;\n offsetY = -(maxY + minY) / 2;\n }\n\n for (i = 0, ilen = arcs.length; i < ilen; ++i) {\n arcs[i]._options = me._resolveDataElementOptions(arcs[i], i);\n }\n\n chart.borderWidth = me.getMaxBorderWidth();\n maxWidth = (chartArea.right - chartArea.left - chart.borderWidth) / ratioX;\n maxHeight = (chartArea.bottom - chartArea.top - chart.borderWidth) / ratioY;\n chart.outerRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0);\n chart.innerRadius = Math.max(chart.outerRadius * cutout, 0);\n chart.radiusLength = (chart.outerRadius - chart.innerRadius) / (me._getVisibleDatasetWeightTotal() || 1);\n chart.offsetX = offsetX * chart.outerRadius;\n chart.offsetY = offsetY * chart.outerRadius;\n meta.total = me.calculateTotal();\n me.outerRadius = chart.outerRadius - chart.radiusLength * me._getRingWeightOffset(me.index);\n me.innerRadius = Math.max(me.outerRadius - chart.radiusLength * chartWeight, 0);\n\n for (i = 0, ilen = arcs.length; i < ilen; ++i) {\n me.updateElement(arcs[i], i, reset);\n }\n },\n updateElement: function (arc, index, reset) {\n var me = this;\n var chart = me.chart;\n var chartArea = chart.chartArea;\n var opts = chart.options;\n var animationOpts = opts.animation;\n var centerX = (chartArea.left + chartArea.right) / 2;\n var centerY = (chartArea.top + chartArea.bottom) / 2;\n var startAngle = opts.rotation; // non reset case handled later\n\n var endAngle = opts.rotation; // non reset case handled later\n\n var dataset = me.getDataset();\n var circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / DOUBLE_PI$1);\n var innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius;\n var outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius;\n var options = arc._options || {};\n helpers$1.extend(arc, {\n // Utility\n _datasetIndex: me.index,\n _index: index,\n // Desired view properties\n _model: {\n backgroundColor: options.backgroundColor,\n borderColor: options.borderColor,\n borderWidth: options.borderWidth,\n borderAlign: options.borderAlign,\n x: centerX + chart.offsetX,\n y: centerY + chart.offsetY,\n startAngle: startAngle,\n endAngle: endAngle,\n circumference: circumference,\n outerRadius: outerRadius,\n innerRadius: innerRadius,\n label: helpers$1.valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index])\n }\n });\n var model = arc._model; // Set correct angles if not resetting\n\n if (!reset || !animationOpts.animateRotate) {\n if (index === 0) {\n model.startAngle = opts.rotation;\n } else {\n model.startAngle = me.getMeta().data[index - 1]._model.endAngle;\n }\n\n model.endAngle = model.startAngle + model.circumference;\n }\n\n arc.pivot();\n },\n calculateTotal: function () {\n var dataset = this.getDataset();\n var meta = this.getMeta();\n var total = 0;\n var value;\n helpers$1.each(meta.data, function (element, index) {\n value = dataset.data[index];\n\n if (!isNaN(value) && !element.hidden) {\n total += Math.abs(value);\n }\n });\n /* if (total === 0) {\n \ttotal = NaN;\n }*/\n\n return total;\n },\n calculateCircumference: function (value) {\n var total = this.getMeta().total;\n\n if (total > 0 && !isNaN(value)) {\n return DOUBLE_PI$1 * (Math.abs(value) / total);\n }\n\n return 0;\n },\n // gets the max border or hover width to properly scale pie charts\n getMaxBorderWidth: function (arcs) {\n var me = this;\n var max = 0;\n var chart = me.chart;\n var i, ilen, meta, arc, controller, options, borderWidth, hoverWidth;\n\n if (!arcs) {\n // Find the outmost visible dataset\n for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) {\n if (chart.isDatasetVisible(i)) {\n meta = chart.getDatasetMeta(i);\n arcs = meta.data;\n\n if (i !== me.index) {\n controller = meta.controller;\n }\n\n break;\n }\n }\n }\n\n if (!arcs) {\n return 0;\n }\n\n for (i = 0, ilen = arcs.length; i < ilen; ++i) {\n arc = arcs[i];\n\n if (controller) {\n controller._configure();\n\n options = controller._resolveDataElementOptions(arc, i);\n } else {\n options = arc._options;\n }\n\n if (options.borderAlign !== 'inner') {\n borderWidth = options.borderWidth;\n hoverWidth = options.hoverBorderWidth;\n max = borderWidth > max ? borderWidth : max;\n max = hoverWidth > max ? hoverWidth : max;\n }\n }\n\n return max;\n },\n\n /**\n * @protected\n */\n setHoverStyle: function (arc) {\n var model = arc._model;\n var options = arc._options;\n var getHoverColor = helpers$1.getHoverColor;\n arc.$previousStyle = {\n backgroundColor: model.backgroundColor,\n borderColor: model.borderColor,\n borderWidth: model.borderWidth\n };\n model.backgroundColor = valueOrDefault$5(options.hoverBackgroundColor, getHoverColor(options.backgroundColor));\n model.borderColor = valueOrDefault$5(options.hoverBorderColor, getHoverColor(options.borderColor));\n model.borderWidth = valueOrDefault$5(options.hoverBorderWidth, options.borderWidth);\n },\n\n /**\n * Get radius length offset of the dataset in relation to the visible datasets weights. This allows determining the inner and outer radius correctly\n * @private\n */\n _getRingWeightOffset: function (datasetIndex) {\n var ringWeightOffset = 0;\n\n for (var i = 0; i < datasetIndex; ++i) {\n if (this.chart.isDatasetVisible(i)) {\n ringWeightOffset += this._getRingWeight(i);\n }\n }\n\n return ringWeightOffset;\n },\n\n /**\n * @private\n */\n _getRingWeight: function (dataSetIndex) {\n return Math.max(valueOrDefault$5(this.chart.data.datasets[dataSetIndex].weight, 1), 0);\n },\n\n /**\n * Returns the sum of all visibile data set weights. This value can be 0.\n * @private\n */\n _getVisibleDatasetWeightTotal: function () {\n return this._getRingWeightOffset(this.chart.data.datasets.length);\n }\n });\n\n core_defaults._set('horizontalBar', {\n hover: {\n mode: 'index',\n axis: 'y'\n },\n scales: {\n xAxes: [{\n type: 'linear',\n position: 'bottom'\n }],\n yAxes: [{\n type: 'category',\n position: 'left',\n offset: true,\n gridLines: {\n offsetGridLines: true\n }\n }]\n },\n elements: {\n rectangle: {\n borderSkipped: 'left'\n }\n },\n tooltips: {\n mode: 'index',\n axis: 'y'\n }\n });\n\n core_defaults._set('global', {\n datasets: {\n horizontalBar: {\n categoryPercentage: 0.8,\n barPercentage: 0.9\n }\n }\n });\n\n var controller_horizontalBar = controller_bar.extend({\n /**\n * @private\n */\n _getValueScaleId: function () {\n return this.getMeta().xAxisID;\n },\n\n /**\n * @private\n */\n _getIndexScaleId: function () {\n return this.getMeta().yAxisID;\n }\n });\n var valueOrDefault$6 = helpers$1.valueOrDefault;\n var resolve$2 = helpers$1.options.resolve;\n var isPointInArea = helpers$1.canvas._isPointInArea;\n\n core_defaults._set('line', {\n showLines: true,\n spanGaps: false,\n hover: {\n mode: 'label'\n },\n scales: {\n xAxes: [{\n type: 'category',\n id: 'x-axis-0'\n }],\n yAxes: [{\n type: 'linear',\n id: 'y-axis-0'\n }]\n }\n });\n\n function scaleClip(scale, halfBorderWidth) {\n var tickOpts = scale && scale.options.ticks || {};\n var reverse = tickOpts.reverse;\n var min = tickOpts.min === undefined ? halfBorderWidth : 0;\n var max = tickOpts.max === undefined ? halfBorderWidth : 0;\n return {\n start: reverse ? max : min,\n end: reverse ? min : max\n };\n }\n\n function defaultClip(xScale, yScale, borderWidth) {\n var halfBorderWidth = borderWidth / 2;\n var x = scaleClip(xScale, halfBorderWidth);\n var y = scaleClip(yScale, halfBorderWidth);\n return {\n top: y.end,\n right: x.end,\n bottom: y.start,\n left: x.start\n };\n }\n\n function toClip(value) {\n var t, r, b, l;\n\n if (helpers$1.isObject(value)) {\n t = value.top;\n r = value.right;\n b = value.bottom;\n l = value.left;\n } else {\n t = r = b = l = value;\n }\n\n return {\n top: t,\n right: r,\n bottom: b,\n left: l\n };\n }\n\n var controller_line = core_datasetController.extend({\n datasetElementType: elements.Line,\n dataElementType: elements.Point,\n\n /**\n * @private\n */\n _datasetElementOptions: ['backgroundColor', 'borderCapStyle', 'borderColor', 'borderDash', 'borderDashOffset', 'borderJoinStyle', 'borderWidth', 'cubicInterpolationMode', 'fill'],\n\n /**\n * @private\n */\n _dataElementOptions: {\n backgroundColor: 'pointBackgroundColor',\n borderColor: 'pointBorderColor',\n borderWidth: 'pointBorderWidth',\n hitRadius: 'pointHitRadius',\n hoverBackgroundColor: 'pointHoverBackgroundColor',\n hoverBorderColor: 'pointHoverBorderColor',\n hoverBorderWidth: 'pointHoverBorderWidth',\n hoverRadius: 'pointHoverRadius',\n pointStyle: 'pointStyle',\n radius: 'pointRadius',\n rotation: 'pointRotation'\n },\n update: function (reset) {\n var me = this;\n var meta = me.getMeta();\n var line = meta.dataset;\n var points = meta.data || [];\n var options = me.chart.options;\n var config = me._config;\n var showLine = me._showLine = valueOrDefault$6(config.showLine, options.showLines);\n var i, ilen;\n me._xScale = me.getScaleForId(meta.xAxisID);\n me._yScale = me.getScaleForId(meta.yAxisID); // Update Line\n\n if (showLine) {\n // Compatibility: If the properties are defined with only the old name, use those values\n if (config.tension !== undefined && config.lineTension === undefined) {\n config.lineTension = config.tension;\n } // Utility\n\n\n line._scale = me._yScale;\n line._datasetIndex = me.index; // Data\n\n line._children = points; // Model\n\n line._model = me._resolveDatasetElementOptions(line);\n line.pivot();\n } // Update Points\n\n\n for (i = 0, ilen = points.length; i < ilen; ++i) {\n me.updateElement(points[i], i, reset);\n }\n\n if (showLine && line._model.tension !== 0) {\n me.updateBezierControlPoints();\n } // Now pivot the point for animation\n\n\n for (i = 0, ilen = points.length; i < ilen; ++i) {\n points[i].pivot();\n }\n },\n updateElement: function (point, index, reset) {\n var me = this;\n var meta = me.getMeta();\n var custom = point.custom || {};\n var dataset = me.getDataset();\n var datasetIndex = me.index;\n var value = dataset.data[index];\n var xScale = me._xScale;\n var yScale = me._yScale;\n var lineModel = meta.dataset._model;\n var x, y;\n\n var options = me._resolveDataElementOptions(point, index);\n\n x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex);\n y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex); // Utility\n\n point._xScale = xScale;\n point._yScale = yScale;\n point._options = options;\n point._datasetIndex = datasetIndex;\n point._index = index; // Desired view properties\n\n point._model = {\n x: x,\n y: y,\n skip: custom.skip || isNaN(x) || isNaN(y),\n // Appearance\n radius: options.radius,\n pointStyle: options.pointStyle,\n rotation: options.rotation,\n backgroundColor: options.backgroundColor,\n borderColor: options.borderColor,\n borderWidth: options.borderWidth,\n tension: valueOrDefault$6(custom.tension, lineModel ? lineModel.tension : 0),\n steppedLine: lineModel ? lineModel.steppedLine : false,\n // Tooltip\n hitRadius: options.hitRadius\n };\n },\n\n /**\n * @private\n */\n _resolveDatasetElementOptions: function (element) {\n var me = this;\n var config = me._config;\n var custom = element.custom || {};\n var options = me.chart.options;\n var lineOptions = options.elements.line;\n\n var values = core_datasetController.prototype._resolveDatasetElementOptions.apply(me, arguments); // The default behavior of lines is to break at null values, according\n // to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158\n // This option gives lines the ability to span gaps\n\n\n values.spanGaps = valueOrDefault$6(config.spanGaps, options.spanGaps);\n values.tension = valueOrDefault$6(config.lineTension, lineOptions.tension);\n values.steppedLine = resolve$2([custom.steppedLine, config.steppedLine, lineOptions.stepped]);\n values.clip = toClip(valueOrDefault$6(config.clip, defaultClip(me._xScale, me._yScale, values.borderWidth)));\n return values;\n },\n calculatePointY: function (value, index, datasetIndex) {\n var me = this;\n var chart = me.chart;\n var yScale = me._yScale;\n var sumPos = 0;\n var sumNeg = 0;\n var i, ds, dsMeta, stackedRightValue, rightValue, metasets, ilen;\n\n if (yScale.options.stacked) {\n rightValue = +yScale.getRightValue(value);\n metasets = chart._getSortedVisibleDatasetMetas();\n ilen = metasets.length;\n\n for (i = 0; i < ilen; ++i) {\n dsMeta = metasets[i];\n\n if (dsMeta.index === datasetIndex) {\n break;\n }\n\n ds = chart.data.datasets[dsMeta.index];\n\n if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id) {\n stackedRightValue = +yScale.getRightValue(ds.data[index]);\n\n if (stackedRightValue < 0) {\n sumNeg += stackedRightValue || 0;\n } else {\n sumPos += stackedRightValue || 0;\n }\n }\n }\n\n if (rightValue < 0) {\n return yScale.getPixelForValue(sumNeg + rightValue);\n }\n\n return yScale.getPixelForValue(sumPos + rightValue);\n }\n\n return yScale.getPixelForValue(value);\n },\n updateBezierControlPoints: function () {\n var me = this;\n var chart = me.chart;\n var meta = me.getMeta();\n var lineModel = meta.dataset._model;\n var area = chart.chartArea;\n var points = meta.data || [];\n var i, ilen, model, controlPoints; // Only consider points that are drawn in case the spanGaps option is used\n\n if (lineModel.spanGaps) {\n points = points.filter(function (pt) {\n return !pt._model.skip;\n });\n }\n\n function capControlPoint(pt, min, max) {\n return Math.max(Math.min(pt, max), min);\n }\n\n if (lineModel.cubicInterpolationMode === 'monotone') {\n helpers$1.splineCurveMonotone(points);\n } else {\n for (i = 0, ilen = points.length; i < ilen; ++i) {\n model = points[i]._model;\n controlPoints = helpers$1.splineCurve(helpers$1.previousItem(points, i)._model, model, helpers$1.nextItem(points, i)._model, lineModel.tension);\n model.controlPointPreviousX = controlPoints.previous.x;\n model.controlPointPreviousY = controlPoints.previous.y;\n model.controlPointNextX = controlPoints.next.x;\n model.controlPointNextY = controlPoints.next.y;\n }\n }\n\n if (chart.options.elements.line.capBezierPoints) {\n for (i = 0, ilen = points.length; i < ilen; ++i) {\n model = points[i]._model;\n\n if (isPointInArea(model, area)) {\n if (i > 0 && isPointInArea(points[i - 1]._model, area)) {\n model.controlPointPreviousX = capControlPoint(model.controlPointPreviousX, area.left, area.right);\n model.controlPointPreviousY = capControlPoint(model.controlPointPreviousY, area.top, area.bottom);\n }\n\n if (i < points.length - 1 && isPointInArea(points[i + 1]._model, area)) {\n model.controlPointNextX = capControlPoint(model.controlPointNextX, area.left, area.right);\n model.controlPointNextY = capControlPoint(model.controlPointNextY, area.top, area.bottom);\n }\n }\n }\n }\n },\n draw: function () {\n var me = this;\n var chart = me.chart;\n var meta = me.getMeta();\n var points = meta.data || [];\n var area = chart.chartArea;\n var canvas = chart.canvas;\n var i = 0;\n var ilen = points.length;\n var clip;\n\n if (me._showLine) {\n clip = meta.dataset._model.clip;\n helpers$1.canvas.clipArea(chart.ctx, {\n left: clip.left === false ? 0 : area.left - clip.left,\n right: clip.right === false ? canvas.width : area.right + clip.right,\n top: clip.top === false ? 0 : area.top - clip.top,\n bottom: clip.bottom === false ? canvas.height : area.bottom + clip.bottom\n });\n meta.dataset.draw();\n helpers$1.canvas.unclipArea(chart.ctx);\n } // Draw the points\n\n\n for (; i < ilen; ++i) {\n points[i].draw(area);\n }\n },\n\n /**\n * @protected\n */\n setHoverStyle: function (point) {\n var model = point._model;\n var options = point._options;\n var getHoverColor = helpers$1.getHoverColor;\n point.$previousStyle = {\n backgroundColor: model.backgroundColor,\n borderColor: model.borderColor,\n borderWidth: model.borderWidth,\n radius: model.radius\n };\n model.backgroundColor = valueOrDefault$6(options.hoverBackgroundColor, getHoverColor(options.backgroundColor));\n model.borderColor = valueOrDefault$6(options.hoverBorderColor, getHoverColor(options.borderColor));\n model.borderWidth = valueOrDefault$6(options.hoverBorderWidth, options.borderWidth);\n model.radius = valueOrDefault$6(options.hoverRadius, options.radius);\n }\n });\n var resolve$3 = helpers$1.options.resolve;\n\n core_defaults._set('polarArea', {\n scale: {\n type: 'radialLinear',\n angleLines: {\n display: false\n },\n gridLines: {\n circular: true\n },\n pointLabels: {\n display: false\n },\n ticks: {\n beginAtZero: true\n }\n },\n // Boolean - Whether to animate the rotation of the chart\n animation: {\n animateRotate: true,\n animateScale: true\n },\n startAngle: -0.5 * Math.PI,\n legendCallback: function (chart) {\n var list = document.createElement('ul');\n var data = chart.data;\n var datasets = data.datasets;\n var labels = data.labels;\n var i, ilen, listItem, listItemSpan;\n list.setAttribute('class', chart.id + '-legend');\n\n if (datasets.length) {\n for (i = 0, ilen = datasets[0].data.length; i < ilen; ++i) {\n listItem = list.appendChild(document.createElement('li'));\n listItemSpan = listItem.appendChild(document.createElement('span'));\n listItemSpan.style.backgroundColor = datasets[0].backgroundColor[i];\n\n if (labels[i]) {\n listItem.appendChild(document.createTextNode(labels[i]));\n }\n }\n }\n\n return list.outerHTML;\n },\n legend: {\n labels: {\n generateLabels: function (chart) {\n var data = chart.data;\n\n if (data.labels.length && data.datasets.length) {\n return data.labels.map(function (label, i) {\n var meta = chart.getDatasetMeta(0);\n var style = meta.controller.getStyle(i);\n return {\n text: label,\n fillStyle: style.backgroundColor,\n strokeStyle: style.borderColor,\n lineWidth: style.borderWidth,\n hidden: isNaN(data.datasets[0].data[i]) || meta.data[i].hidden,\n // Extra data used for toggling the correct item\n index: i\n };\n });\n }\n\n return [];\n }\n },\n onClick: function (e, legendItem) {\n var index = legendItem.index;\n var chart = this.chart;\n var i, ilen, meta;\n\n for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {\n meta = chart.getDatasetMeta(i);\n meta.data[index].hidden = !meta.data[index].hidden;\n }\n\n chart.update();\n }\n },\n // Need to override these to give a nice default\n tooltips: {\n callbacks: {\n title: function () {\n return '';\n },\n label: function (item, data) {\n return data.labels[item.index] + ': ' + item.yLabel;\n }\n }\n }\n });\n\n var controller_polarArea = core_datasetController.extend({\n dataElementType: elements.Arc,\n linkScales: helpers$1.noop,\n\n /**\n * @private\n */\n _dataElementOptions: ['backgroundColor', 'borderColor', 'borderWidth', 'borderAlign', 'hoverBackgroundColor', 'hoverBorderColor', 'hoverBorderWidth'],\n\n /**\n * @private\n */\n _getIndexScaleId: function () {\n return this.chart.scale.id;\n },\n\n /**\n * @private\n */\n _getValueScaleId: function () {\n return this.chart.scale.id;\n },\n update: function (reset) {\n var me = this;\n var dataset = me.getDataset();\n var meta = me.getMeta();\n var start = me.chart.options.startAngle || 0;\n var starts = me._starts = [];\n var angles = me._angles = [];\n var arcs = meta.data;\n var i, ilen, angle;\n\n me._updateRadius();\n\n meta.count = me.countVisibleElements();\n\n for (i = 0, ilen = dataset.data.length; i < ilen; i++) {\n starts[i] = start;\n angle = me._computeAngle(i);\n angles[i] = angle;\n start += angle;\n }\n\n for (i = 0, ilen = arcs.length; i < ilen; ++i) {\n arcs[i]._options = me._resolveDataElementOptions(arcs[i], i);\n me.updateElement(arcs[i], i, reset);\n }\n },\n\n /**\n * @private\n */\n _updateRadius: function () {\n var me = this;\n var chart = me.chart;\n var chartArea = chart.chartArea;\n var opts = chart.options;\n var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);\n chart.outerRadius = Math.max(minSize / 2, 0);\n chart.innerRadius = Math.max(opts.cutoutPercentage ? chart.outerRadius / 100 * opts.cutoutPercentage : 1, 0);\n chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();\n me.outerRadius = chart.outerRadius - chart.radiusLength * me.index;\n me.innerRadius = me.outerRadius - chart.radiusLength;\n },\n updateElement: function (arc, index, reset) {\n var me = this;\n var chart = me.chart;\n var dataset = me.getDataset();\n var opts = chart.options;\n var animationOpts = opts.animation;\n var scale = chart.scale;\n var labels = chart.data.labels;\n var centerX = scale.xCenter;\n var centerY = scale.yCenter; // var negHalfPI = -0.5 * Math.PI;\n\n var datasetStartAngle = opts.startAngle;\n var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);\n var startAngle = me._starts[index];\n var endAngle = startAngle + (arc.hidden ? 0 : me._angles[index]);\n var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);\n var options = arc._options || {};\n helpers$1.extend(arc, {\n // Utility\n _datasetIndex: me.index,\n _index: index,\n _scale: scale,\n // Desired view properties\n _model: {\n backgroundColor: options.backgroundColor,\n borderColor: options.borderColor,\n borderWidth: options.borderWidth,\n borderAlign: options.borderAlign,\n x: centerX,\n y: centerY,\n innerRadius: 0,\n outerRadius: reset ? resetRadius : distance,\n startAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle,\n endAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle,\n label: helpers$1.valueAtIndexOrDefault(labels, index, labels[index])\n }\n });\n arc.pivot();\n },\n countVisibleElements: function () {\n var dataset = this.getDataset();\n var meta = this.getMeta();\n var count = 0;\n helpers$1.each(meta.data, function (element, index) {\n if (!isNaN(dataset.data[index]) && !element.hidden) {\n count++;\n }\n });\n return count;\n },\n\n /**\n * @protected\n */\n setHoverStyle: function (arc) {\n var model = arc._model;\n var options = arc._options;\n var getHoverColor = helpers$1.getHoverColor;\n var valueOrDefault = helpers$1.valueOrDefault;\n arc.$previousStyle = {\n backgroundColor: model.backgroundColor,\n borderColor: model.borderColor,\n borderWidth: model.borderWidth\n };\n model.backgroundColor = valueOrDefault(options.hoverBackgroundColor, getHoverColor(options.backgroundColor));\n model.borderColor = valueOrDefault(options.hoverBorderColor, getHoverColor(options.borderColor));\n model.borderWidth = valueOrDefault(options.hoverBorderWidth, options.borderWidth);\n },\n\n /**\n * @private\n */\n _computeAngle: function (index) {\n var me = this;\n var count = this.getMeta().count;\n var dataset = me.getDataset();\n var meta = me.getMeta();\n\n if (isNaN(dataset.data[index]) || meta.data[index].hidden) {\n return 0;\n } // Scriptable options\n\n\n var context = {\n chart: me.chart,\n dataIndex: index,\n dataset: dataset,\n datasetIndex: me.index\n };\n return resolve$3([me.chart.options.elements.arc.angle, 2 * Math.PI / count], context, index);\n }\n });\n\n core_defaults._set('pie', helpers$1.clone(core_defaults.doughnut));\n\n core_defaults._set('pie', {\n cutoutPercentage: 0\n }); // Pie charts are Doughnut chart with different defaults\n\n\n var controller_pie = controller_doughnut;\n var valueOrDefault$7 = helpers$1.valueOrDefault;\n\n core_defaults._set('radar', {\n spanGaps: false,\n scale: {\n type: 'radialLinear'\n },\n elements: {\n line: {\n fill: 'start',\n tension: 0 // no bezier in radar\n\n }\n }\n });\n\n var controller_radar = core_datasetController.extend({\n datasetElementType: elements.Line,\n dataElementType: elements.Point,\n linkScales: helpers$1.noop,\n\n /**\n * @private\n */\n _datasetElementOptions: ['backgroundColor', 'borderWidth', 'borderColor', 'borderCapStyle', 'borderDash', 'borderDashOffset', 'borderJoinStyle', 'fill'],\n\n /**\n * @private\n */\n _dataElementOptions: {\n backgroundColor: 'pointBackgroundColor',\n borderColor: 'pointBorderColor',\n borderWidth: 'pointBorderWidth',\n hitRadius: 'pointHitRadius',\n hoverBackgroundColor: 'pointHoverBackgroundColor',\n hoverBorderColor: 'pointHoverBorderColor',\n hoverBorderWidth: 'pointHoverBorderWidth',\n hoverRadius: 'pointHoverRadius',\n pointStyle: 'pointStyle',\n radius: 'pointRadius',\n rotation: 'pointRotation'\n },\n\n /**\n * @private\n */\n _getIndexScaleId: function () {\n return this.chart.scale.id;\n },\n\n /**\n * @private\n */\n _getValueScaleId: function () {\n return this.chart.scale.id;\n },\n update: function (reset) {\n var me = this;\n var meta = me.getMeta();\n var line = meta.dataset;\n var points = meta.data || [];\n var scale = me.chart.scale;\n var config = me._config;\n var i, ilen; // Compatibility: If the properties are defined with only the old name, use those values\n\n if (config.tension !== undefined && config.lineTension === undefined) {\n config.lineTension = config.tension;\n } // Utility\n\n\n line._scale = scale;\n line._datasetIndex = me.index; // Data\n\n line._children = points;\n line._loop = true; // Model\n\n line._model = me._resolveDatasetElementOptions(line);\n line.pivot(); // Update Points\n\n for (i = 0, ilen = points.length; i < ilen; ++i) {\n me.updateElement(points[i], i, reset);\n } // Update bezier control points\n\n\n me.updateBezierControlPoints(); // Now pivot the point for animation\n\n for (i = 0, ilen = points.length; i < ilen; ++i) {\n points[i].pivot();\n }\n },\n updateElement: function (point, index, reset) {\n var me = this;\n var custom = point.custom || {};\n var dataset = me.getDataset();\n var scale = me.chart.scale;\n var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]);\n\n var options = me._resolveDataElementOptions(point, index);\n\n var lineModel = me.getMeta().dataset._model;\n\n var x = reset ? scale.xCenter : pointPosition.x;\n var y = reset ? scale.yCenter : pointPosition.y; // Utility\n\n point._scale = scale;\n point._options = options;\n point._datasetIndex = me.index;\n point._index = index; // Desired view properties\n\n point._model = {\n x: x,\n // value not used in dataset scale, but we want a consistent API between scales\n y: y,\n skip: custom.skip || isNaN(x) || isNaN(y),\n // Appearance\n radius: options.radius,\n pointStyle: options.pointStyle,\n rotation: options.rotation,\n backgroundColor: options.backgroundColor,\n borderColor: options.borderColor,\n borderWidth: options.borderWidth,\n tension: valueOrDefault$7(custom.tension, lineModel ? lineModel.tension : 0),\n // Tooltip\n hitRadius: options.hitRadius\n };\n },\n\n /**\n * @private\n */\n _resolveDatasetElementOptions: function () {\n var me = this;\n var config = me._config;\n var options = me.chart.options;\n\n var values = core_datasetController.prototype._resolveDatasetElementOptions.apply(me, arguments);\n\n values.spanGaps = valueOrDefault$7(config.spanGaps, options.spanGaps);\n values.tension = valueOrDefault$7(config.lineTension, options.elements.line.tension);\n return values;\n },\n updateBezierControlPoints: function () {\n var me = this;\n var meta = me.getMeta();\n var area = me.chart.chartArea;\n var points = meta.data || [];\n var i, ilen, model, controlPoints; // Only consider points that are drawn in case the spanGaps option is used\n\n if (meta.dataset._model.spanGaps) {\n points = points.filter(function (pt) {\n return !pt._model.skip;\n });\n }\n\n function capControlPoint(pt, min, max) {\n return Math.max(Math.min(pt, max), min);\n }\n\n for (i = 0, ilen = points.length; i < ilen; ++i) {\n model = points[i]._model;\n controlPoints = helpers$1.splineCurve(helpers$1.previousItem(points, i, true)._model, model, helpers$1.nextItem(points, i, true)._model, model.tension); // Prevent the bezier going outside of the bounds of the graph\n\n model.controlPointPreviousX = capControlPoint(controlPoints.previous.x, area.left, area.right);\n model.controlPointPreviousY = capControlPoint(controlPoints.previous.y, area.top, area.bottom);\n model.controlPointNextX = capControlPoint(controlPoints.next.x, area.left, area.right);\n model.controlPointNextY = capControlPoint(controlPoints.next.y, area.top, area.bottom);\n }\n },\n setHoverStyle: function (point) {\n var model = point._model;\n var options = point._options;\n var getHoverColor = helpers$1.getHoverColor;\n point.$previousStyle = {\n backgroundColor: model.backgroundColor,\n borderColor: model.borderColor,\n borderWidth: model.borderWidth,\n radius: model.radius\n };\n model.backgroundColor = valueOrDefault$7(options.hoverBackgroundColor, getHoverColor(options.backgroundColor));\n model.borderColor = valueOrDefault$7(options.hoverBorderColor, getHoverColor(options.borderColor));\n model.borderWidth = valueOrDefault$7(options.hoverBorderWidth, options.borderWidth);\n model.radius = valueOrDefault$7(options.hoverRadius, options.radius);\n }\n });\n\n core_defaults._set('scatter', {\n hover: {\n mode: 'single'\n },\n scales: {\n xAxes: [{\n id: 'x-axis-1',\n // need an ID so datasets can reference the scale\n type: 'linear',\n // scatter should not use a category axis\n position: 'bottom'\n }],\n yAxes: [{\n id: 'y-axis-1',\n type: 'linear',\n position: 'left'\n }]\n },\n tooltips: {\n callbacks: {\n title: function () {\n return ''; // doesn't make sense for scatter since data are formatted as a point\n },\n label: function (item) {\n return '(' + item.xLabel + ', ' + item.yLabel + ')';\n }\n }\n }\n });\n\n core_defaults._set('global', {\n datasets: {\n scatter: {\n showLine: false\n }\n }\n }); // Scatter charts use line controllers\n\n\n var controller_scatter = controller_line; // NOTE export a map in which the key represents the controller type, not\n // the class, and so must be CamelCase in order to be correctly retrieved\n // by the controller in core.controller.js (`controllers[meta.type]`).\n\n var controllers = {\n bar: controller_bar,\n bubble: controller_bubble,\n doughnut: controller_doughnut,\n horizontalBar: controller_horizontalBar,\n line: controller_line,\n polarArea: controller_polarArea,\n pie: controller_pie,\n radar: controller_radar,\n scatter: controller_scatter\n };\n /**\n * Helper function to get relative position for an event\n * @param {Event|IEvent} event - The event to get the position for\n * @param {Chart} chart - The chart\n * @returns {object} the event position\n */\n\n function getRelativePosition(e, chart) {\n if (e.native) {\n return {\n x: e.x,\n y: e.y\n };\n }\n\n return helpers$1.getRelativePosition(e, chart);\n }\n /**\n * Helper function to traverse all of the visible elements in the chart\n * @param {Chart} chart - the chart\n * @param {function} handler - the callback to execute for each visible item\n */\n\n\n function parseVisibleItems(chart, handler) {\n var metasets = chart._getSortedVisibleDatasetMetas();\n\n var metadata, i, j, ilen, jlen, element;\n\n for (i = 0, ilen = metasets.length; i < ilen; ++i) {\n metadata = metasets[i].data;\n\n for (j = 0, jlen = metadata.length; j < jlen; ++j) {\n element = metadata[j];\n\n if (!element._view.skip) {\n handler(element);\n }\n }\n }\n }\n /**\n * Helper function to get the items that intersect the event position\n * @param {ChartElement[]} items - elements to filter\n * @param {object} position - the point to be nearest to\n * @return {ChartElement[]} the nearest items\n */\n\n\n function getIntersectItems(chart, position) {\n var elements = [];\n parseVisibleItems(chart, function (element) {\n if (element.inRange(position.x, position.y)) {\n elements.push(element);\n }\n });\n return elements;\n }\n /**\n * Helper function to get the items nearest to the event position considering all visible items in teh chart\n * @param {Chart} chart - the chart to look at elements from\n * @param {object} position - the point to be nearest to\n * @param {boolean} intersect - if true, only consider items that intersect the position\n * @param {function} distanceMetric - function to provide the distance between points\n * @return {ChartElement[]} the nearest items\n */\n\n\n function getNearestItems(chart, position, intersect, distanceMetric) {\n var minDistance = Number.POSITIVE_INFINITY;\n var nearestItems = [];\n parseVisibleItems(chart, function (element) {\n if (intersect && !element.inRange(position.x, position.y)) {\n return;\n }\n\n var center = element.getCenterPoint();\n var distance = distanceMetric(position, center);\n\n if (distance < minDistance) {\n nearestItems = [element];\n minDistance = distance;\n } else if (distance === minDistance) {\n // Can have multiple items at the same distance in which case we sort by size\n nearestItems.push(element);\n }\n });\n return nearestItems;\n }\n /**\n * Get a distance metric function for two points based on the\n * axis mode setting\n * @param {string} axis - the axis mode. x|y|xy\n */\n\n\n function getDistanceMetricForAxis(axis) {\n var useX = axis.indexOf('x') !== -1;\n var useY = axis.indexOf('y') !== -1;\n return function (pt1, pt2) {\n var deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0;\n var deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0;\n return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));\n };\n }\n\n function indexMode(chart, e, options) {\n var position = getRelativePosition(e, chart); // Default axis for index mode is 'x' to match old behaviour\n\n options.axis = options.axis || 'x';\n var distanceMetric = getDistanceMetricForAxis(options.axis);\n var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);\n var elements = [];\n\n if (!items.length) {\n return [];\n }\n\n chart._getSortedVisibleDatasetMetas().forEach(function (meta) {\n var element = meta.data[items[0]._index]; // don't count items that are skipped (null data)\n\n if (element && !element._view.skip) {\n elements.push(element);\n }\n });\n\n return elements;\n }\n /**\n * @interface IInteractionOptions\n */\n\n /**\n * If true, only consider items that intersect the point\n * @name IInterfaceOptions#boolean\n * @type Boolean\n */\n\n /**\n * Contains interaction related functions\n * @namespace Chart.Interaction\n */\n\n\n var core_interaction = {\n // Helper function for different modes\n modes: {\n single: function (chart, e) {\n var position = getRelativePosition(e, chart);\n var elements = [];\n parseVisibleItems(chart, function (element) {\n if (element.inRange(position.x, position.y)) {\n elements.push(element);\n return elements;\n }\n });\n return elements.slice(0, 1);\n },\n\n /**\n * @function Chart.Interaction.modes.label\n * @deprecated since version 2.4.0\n * @todo remove at version 3\n * @private\n */\n label: indexMode,\n\n /**\n * Returns items at the same index. If the options.intersect parameter is true, we only return items if we intersect something\n * If the options.intersect mode is false, we find the nearest item and return the items at the same index as that item\n * @function Chart.Interaction.modes.index\n * @since v2.4.0\n * @param {Chart} chart - the chart we are returning items from\n * @param {Event} e - the event we are find things at\n * @param {IInteractionOptions} options - options to use during interaction\n * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned\n */\n index: indexMode,\n\n /**\n * Returns items in the same dataset. If the options.intersect parameter is true, we only return items if we intersect something\n * If the options.intersect is false, we find the nearest item and return the items in that dataset\n * @function Chart.Interaction.modes.dataset\n * @param {Chart} chart - the chart we are returning items from\n * @param {Event} e - the event we are find things at\n * @param {IInteractionOptions} options - options to use during interaction\n * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned\n */\n dataset: function (chart, e, options) {\n var position = getRelativePosition(e, chart);\n options.axis = options.axis || 'xy';\n var distanceMetric = getDistanceMetricForAxis(options.axis);\n var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);\n\n if (items.length > 0) {\n items = chart.getDatasetMeta(items[0]._datasetIndex).data;\n }\n\n return items;\n },\n\n /**\n * @function Chart.Interaction.modes.x-axis\n * @deprecated since version 2.4.0. Use index mode and intersect == true\n * @todo remove at version 3\n * @private\n */\n 'x-axis': function (chart, e) {\n return indexMode(chart, e, {\n intersect: false\n });\n },\n\n /**\n * Point mode returns all elements that hit test based on the event position\n * of the event\n * @function Chart.Interaction.modes.intersect\n * @param {Chart} chart - the chart we are returning items from\n * @param {Event} e - the event we are find things at\n * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned\n */\n point: function (chart, e) {\n var position = getRelativePosition(e, chart);\n return getIntersectItems(chart, position);\n },\n\n /**\n * nearest mode returns the element closest to the point\n * @function Chart.Interaction.modes.intersect\n * @param {Chart} chart - the chart we are returning items from\n * @param {Event} e - the event we are find things at\n * @param {IInteractionOptions} options - options to use\n * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned\n */\n nearest: function (chart, e, options) {\n var position = getRelativePosition(e, chart);\n options.axis = options.axis || 'xy';\n var distanceMetric = getDistanceMetricForAxis(options.axis);\n return getNearestItems(chart, position, options.intersect, distanceMetric);\n },\n\n /**\n * x mode returns the elements that hit-test at the current x coordinate\n * @function Chart.Interaction.modes.x\n * @param {Chart} chart - the chart we are returning items from\n * @param {Event} e - the event we are find things at\n * @param {IInteractionOptions} options - options to use\n * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned\n */\n x: function (chart, e, options) {\n var position = getRelativePosition(e, chart);\n var items = [];\n var intersectsItem = false;\n parseVisibleItems(chart, function (element) {\n if (element.inXRange(position.x)) {\n items.push(element);\n }\n\n if (element.inRange(position.x, position.y)) {\n intersectsItem = true;\n }\n }); // If we want to trigger on an intersect and we don't have any items\n // that intersect the position, return nothing\n\n if (options.intersect && !intersectsItem) {\n items = [];\n }\n\n return items;\n },\n\n /**\n * y mode returns the elements that hit-test at the current y coordinate\n * @function Chart.Interaction.modes.y\n * @param {Chart} chart - the chart we are returning items from\n * @param {Event} e - the event we are find things at\n * @param {IInteractionOptions} options - options to use\n * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned\n */\n y: function (chart, e, options) {\n var position = getRelativePosition(e, chart);\n var items = [];\n var intersectsItem = false;\n parseVisibleItems(chart, function (element) {\n if (element.inYRange(position.y)) {\n items.push(element);\n }\n\n if (element.inRange(position.x, position.y)) {\n intersectsItem = true;\n }\n }); // If we want to trigger on an intersect and we don't have any items\n // that intersect the position, return nothing\n\n if (options.intersect && !intersectsItem) {\n items = [];\n }\n\n return items;\n }\n }\n };\n var extend = helpers$1.extend;\n\n function filterByPosition(array, position) {\n return helpers$1.where(array, function (v) {\n return v.pos === position;\n });\n }\n\n function sortByWeight(array, reverse) {\n return array.sort(function (a, b) {\n var v0 = reverse ? b : a;\n var v1 = reverse ? a : b;\n return v0.weight === v1.weight ? v0.index - v1.index : v0.weight - v1.weight;\n });\n }\n\n function wrapBoxes(boxes) {\n var layoutBoxes = [];\n var i, ilen, box;\n\n for (i = 0, ilen = (boxes || []).length; i < ilen; ++i) {\n box = boxes[i];\n layoutBoxes.push({\n index: i,\n box: box,\n pos: box.position,\n horizontal: box.isHorizontal(),\n weight: box.weight\n });\n }\n\n return layoutBoxes;\n }\n\n function setLayoutDims(layouts, params) {\n var i, ilen, layout;\n\n for (i = 0, ilen = layouts.length; i < ilen; ++i) {\n layout = layouts[i]; // store width used instead of chartArea.w in fitBoxes\n\n layout.width = layout.horizontal ? layout.box.fullWidth && params.availableWidth : params.vBoxMaxWidth; // store height used instead of chartArea.h in fitBoxes\n\n layout.height = layout.horizontal && params.hBoxMaxHeight;\n }\n }\n\n function buildLayoutBoxes(boxes) {\n var layoutBoxes = wrapBoxes(boxes);\n var left = sortByWeight(filterByPosition(layoutBoxes, 'left'), true);\n var right = sortByWeight(filterByPosition(layoutBoxes, 'right'));\n var top = sortByWeight(filterByPosition(layoutBoxes, 'top'), true);\n var bottom = sortByWeight(filterByPosition(layoutBoxes, 'bottom'));\n return {\n leftAndTop: left.concat(top),\n rightAndBottom: right.concat(bottom),\n chartArea: filterByPosition(layoutBoxes, 'chartArea'),\n vertical: left.concat(right),\n horizontal: top.concat(bottom)\n };\n }\n\n function getCombinedMax(maxPadding, chartArea, a, b) {\n return Math.max(maxPadding[a], chartArea[a]) + Math.max(maxPadding[b], chartArea[b]);\n }\n\n function updateDims(chartArea, params, layout) {\n var box = layout.box;\n var maxPadding = chartArea.maxPadding;\n var newWidth, newHeight;\n\n if (layout.size) {\n // this layout was already counted for, lets first reduce old size\n chartArea[layout.pos] -= layout.size;\n }\n\n layout.size = layout.horizontal ? box.height : box.width;\n chartArea[layout.pos] += layout.size;\n\n if (box.getPadding) {\n var boxPadding = box.getPadding();\n maxPadding.top = Math.max(maxPadding.top, boxPadding.top);\n maxPadding.left = Math.max(maxPadding.left, boxPadding.left);\n maxPadding.bottom = Math.max(maxPadding.bottom, boxPadding.bottom);\n maxPadding.right = Math.max(maxPadding.right, boxPadding.right);\n }\n\n newWidth = params.outerWidth - getCombinedMax(maxPadding, chartArea, 'left', 'right');\n newHeight = params.outerHeight - getCombinedMax(maxPadding, chartArea, 'top', 'bottom');\n\n if (newWidth !== chartArea.w || newHeight !== chartArea.h) {\n chartArea.w = newWidth;\n chartArea.h = newHeight; // return true if chart area changed in layout's direction\n\n return layout.horizontal ? newWidth !== chartArea.w : newHeight !== chartArea.h;\n }\n }\n\n function handleMaxPadding(chartArea) {\n var maxPadding = chartArea.maxPadding;\n\n function updatePos(pos) {\n var change = Math.max(maxPadding[pos] - chartArea[pos], 0);\n chartArea[pos] += change;\n return change;\n }\n\n chartArea.y += updatePos('top');\n chartArea.x += updatePos('left');\n updatePos('right');\n updatePos('bottom');\n }\n\n function getMargins(horizontal, chartArea) {\n var maxPadding = chartArea.maxPadding;\n\n function marginForPositions(positions) {\n var margin = {\n left: 0,\n top: 0,\n right: 0,\n bottom: 0\n };\n positions.forEach(function (pos) {\n margin[pos] = Math.max(chartArea[pos], maxPadding[pos]);\n });\n return margin;\n }\n\n return horizontal ? marginForPositions(['left', 'right']) : marginForPositions(['top', 'bottom']);\n }\n\n function fitBoxes(boxes, chartArea, params) {\n var refitBoxes = [];\n var i, ilen, layout, box, refit, changed;\n\n for (i = 0, ilen = boxes.length; i < ilen; ++i) {\n layout = boxes[i];\n box = layout.box;\n box.update(layout.width || chartArea.w, layout.height || chartArea.h, getMargins(layout.horizontal, chartArea));\n\n if (updateDims(chartArea, params, layout)) {\n changed = true;\n\n if (refitBoxes.length) {\n // Dimensions changed and there were non full width boxes before this\n // -> we have to refit those\n refit = true;\n }\n }\n\n if (!box.fullWidth) {\n // fullWidth boxes don't need to be re-fitted in any case\n refitBoxes.push(layout);\n }\n }\n\n return refit ? fitBoxes(refitBoxes, chartArea, params) || changed : changed;\n }\n\n function placeBoxes(boxes, chartArea, params) {\n var userPadding = params.padding;\n var x = chartArea.x;\n var y = chartArea.y;\n var i, ilen, layout, box;\n\n for (i = 0, ilen = boxes.length; i < ilen; ++i) {\n layout = boxes[i];\n box = layout.box;\n\n if (layout.horizontal) {\n box.left = box.fullWidth ? userPadding.left : chartArea.left;\n box.right = box.fullWidth ? params.outerWidth - userPadding.right : chartArea.left + chartArea.w;\n box.top = y;\n box.bottom = y + box.height;\n box.width = box.right - box.left;\n y = box.bottom;\n } else {\n box.left = x;\n box.right = x + box.width;\n box.top = chartArea.top;\n box.bottom = chartArea.top + chartArea.h;\n box.height = box.bottom - box.top;\n x = box.right;\n }\n }\n\n chartArea.x = x;\n chartArea.y = y;\n }\n\n core_defaults._set('global', {\n layout: {\n padding: {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n }\n }\n });\n /**\n * @interface ILayoutItem\n * @prop {string} position - The position of the item in the chart layout. Possible values are\n * 'left', 'top', 'right', 'bottom', and 'chartArea'\n * @prop {number} weight - The weight used to sort the item. Higher weights are further away from the chart area\n * @prop {boolean} fullWidth - if true, and the item is horizontal, then push vertical boxes down\n * @prop {function} isHorizontal - returns true if the layout item is horizontal (ie. top or bottom)\n * @prop {function} update - Takes two parameters: width and height. Returns size of item\n * @prop {function} getPadding - Returns an object with padding on the edges\n * @prop {number} width - Width of item. Must be valid after update()\n * @prop {number} height - Height of item. Must be valid after update()\n * @prop {number} left - Left edge of the item. Set by layout system and cannot be used in update\n * @prop {number} top - Top edge of the item. Set by layout system and cannot be used in update\n * @prop {number} right - Right edge of the item. Set by layout system and cannot be used in update\n * @prop {number} bottom - Bottom edge of the item. Set by layout system and cannot be used in update\n */\n // The layout service is very self explanatory. It's responsible for the layout within a chart.\n // Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need\n // It is this service's responsibility of carrying out that layout.\n\n\n var core_layouts = {\n defaults: {},\n\n /**\n * Register a box to a chart.\n * A box is simply a reference to an object that requires layout. eg. Scales, Legend, Title.\n * @param {Chart} chart - the chart to use\n * @param {ILayoutItem} item - the item to add to be layed out\n */\n addBox: function (chart, item) {\n if (!chart.boxes) {\n chart.boxes = [];\n } // initialize item with default values\n\n\n item.fullWidth = item.fullWidth || false;\n item.position = item.position || 'top';\n item.weight = item.weight || 0;\n\n item._layers = item._layers || function () {\n return [{\n z: 0,\n draw: function () {\n item.draw.apply(item, arguments);\n }\n }];\n };\n\n chart.boxes.push(item);\n },\n\n /**\n * Remove a layoutItem from a chart\n * @param {Chart} chart - the chart to remove the box from\n * @param {ILayoutItem} layoutItem - the item to remove from the layout\n */\n removeBox: function (chart, layoutItem) {\n var index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1;\n\n if (index !== -1) {\n chart.boxes.splice(index, 1);\n }\n },\n\n /**\n * Sets (or updates) options on the given `item`.\n * @param {Chart} chart - the chart in which the item lives (or will be added to)\n * @param {ILayoutItem} item - the item to configure with the given options\n * @param {object} options - the new item options.\n */\n configure: function (chart, item, options) {\n var props = ['fullWidth', 'position', 'weight'];\n var ilen = props.length;\n var i = 0;\n var prop;\n\n for (; i < ilen; ++i) {\n prop = props[i];\n\n if (options.hasOwnProperty(prop)) {\n item[prop] = options[prop];\n }\n }\n },\n\n /**\n * Fits boxes of the given chart into the given size by having each box measure itself\n * then running a fitting algorithm\n * @param {Chart} chart - the chart\n * @param {number} width - the width to fit into\n * @param {number} height - the height to fit into\n */\n update: function (chart, width, height) {\n if (!chart) {\n return;\n }\n\n var layoutOptions = chart.options.layout || {};\n var padding = helpers$1.options.toPadding(layoutOptions.padding);\n var availableWidth = width - padding.width;\n var availableHeight = height - padding.height;\n var boxes = buildLayoutBoxes(chart.boxes);\n var verticalBoxes = boxes.vertical;\n var horizontalBoxes = boxes.horizontal; // Essentially we now have any number of boxes on each of the 4 sides.\n // Our canvas looks like the following.\n // The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and\n // B1 is the bottom axis\n // There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays\n // These locations are single-box locations only, when trying to register a chartArea location that is already taken,\n // an error will be thrown.\n //\n // |----------------------------------------------------|\n // | T1 (Full Width) |\n // |----------------------------------------------------|\n // | | | T2 | |\n // | |----|-------------------------------------|----|\n // | | | C1 | | C2 | |\n // | | |----| |----| |\n // | | | | |\n // | L1 | L2 | ChartArea (C0) | R1 |\n // | | | | |\n // | | |----| |----| |\n // | | | C3 | | C4 | |\n // | |----|-------------------------------------|----|\n // | | | B1 | |\n // |----------------------------------------------------|\n // | B2 (Full Width) |\n // |----------------------------------------------------|\n //\n\n var params = Object.freeze({\n outerWidth: width,\n outerHeight: height,\n padding: padding,\n availableWidth: availableWidth,\n vBoxMaxWidth: availableWidth / 2 / verticalBoxes.length,\n hBoxMaxHeight: availableHeight / 2\n });\n var chartArea = extend({\n maxPadding: extend({}, padding),\n w: availableWidth,\n h: availableHeight,\n x: padding.left,\n y: padding.top\n }, padding);\n setLayoutDims(verticalBoxes.concat(horizontalBoxes), params); // First fit vertical boxes\n\n fitBoxes(verticalBoxes, chartArea, params); // Then fit horizontal boxes\n\n if (fitBoxes(horizontalBoxes, chartArea, params)) {\n // if the area changed, re-fit vertical boxes\n fitBoxes(verticalBoxes, chartArea, params);\n }\n\n handleMaxPadding(chartArea); // Finally place the boxes to correct coordinates\n\n placeBoxes(boxes.leftAndTop, chartArea, params); // Move to opposite side of chart\n\n chartArea.x += chartArea.w;\n chartArea.y += chartArea.h;\n placeBoxes(boxes.rightAndBottom, chartArea, params);\n chart.chartArea = {\n left: chartArea.left,\n top: chartArea.top,\n right: chartArea.left + chartArea.w,\n bottom: chartArea.top + chartArea.h\n }; // Finally update boxes in chartArea (radial scale for example)\n\n helpers$1.each(boxes.chartArea, function (layout) {\n var box = layout.box;\n extend(box, chart.chartArea);\n box.update(chartArea.w, chartArea.h);\n });\n }\n };\n /**\n * Platform fallback implementation (minimal).\n * @see https://github.com/chartjs/Chart.js/pull/4591#issuecomment-319575939\n */\n\n var platform_basic = {\n acquireContext: function (item) {\n if (item && item.canvas) {\n // Support for any object associated to a canvas (including a context2d)\n item = item.canvas;\n }\n\n return item && item.getContext('2d') || null;\n }\n };\n var platform_dom = \"/*\\n * DOM element rendering detection\\n * https://davidwalsh.name/detect-node-insertion\\n */\\n@keyframes chartjs-render-animation {\\n\\tfrom { opacity: 0.99; }\\n\\tto { opacity: 1; }\\n}\\n\\n.chartjs-render-monitor {\\n\\tanimation: chartjs-render-animation 0.001s;\\n}\\n\\n/*\\n * DOM element resizing detection\\n * https://github.com/marcj/css-element-queries\\n */\\n.chartjs-size-monitor,\\n.chartjs-size-monitor-expand,\\n.chartjs-size-monitor-shrink {\\n\\tposition: absolute;\\n\\tdirection: ltr;\\n\\tleft: 0;\\n\\ttop: 0;\\n\\tright: 0;\\n\\tbottom: 0;\\n\\toverflow: hidden;\\n\\tpointer-events: none;\\n\\tvisibility: hidden;\\n\\tz-index: -1;\\n}\\n\\n.chartjs-size-monitor-expand > div {\\n\\tposition: absolute;\\n\\twidth: 1000000px;\\n\\theight: 1000000px;\\n\\tleft: 0;\\n\\ttop: 0;\\n}\\n\\n.chartjs-size-monitor-shrink > div {\\n\\tposition: absolute;\\n\\twidth: 200%;\\n\\theight: 200%;\\n\\tleft: 0;\\n\\ttop: 0;\\n}\\n\";\n var platform_dom$1 =\n /*#__PURE__*/\n Object.freeze({\n __proto__: null,\n 'default': platform_dom\n });\n var stylesheet = getCjsExportFromNamespace(platform_dom$1);\n var EXPANDO_KEY = '$chartjs';\n var CSS_PREFIX = 'chartjs-';\n var CSS_SIZE_MONITOR = CSS_PREFIX + 'size-monitor';\n var CSS_RENDER_MONITOR = CSS_PREFIX + 'render-monitor';\n var CSS_RENDER_ANIMATION = CSS_PREFIX + 'render-animation';\n var ANIMATION_START_EVENTS = ['animationstart', 'webkitAnimationStart'];\n /**\n * DOM event types -> Chart.js event types.\n * Note: only events with different types are mapped.\n * @see https://developer.mozilla.org/en-US/docs/Web/Events\n */\n\n var EVENT_TYPES = {\n touchstart: 'mousedown',\n touchmove: 'mousemove',\n touchend: 'mouseup',\n pointerenter: 'mouseenter',\n pointerdown: 'mousedown',\n pointermove: 'mousemove',\n pointerup: 'mouseup',\n pointerleave: 'mouseout',\n pointerout: 'mouseout'\n };\n /**\n * The \"used\" size is the final value of a dimension property after all calculations have\n * been performed. This method uses the computed style of `element` but returns undefined\n * if the computed style is not expressed in pixels. That can happen in some cases where\n * `element` has a size relative to its parent and this last one is not yet displayed,\n * for example because of `display: none` on a parent node.\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value\n * @returns {number} Size in pixels or undefined if unknown.\n */\n\n function readUsedSize(element, property) {\n var value = helpers$1.getStyle(element, property);\n var matches = value && value.match(/^(\\d+)(\\.\\d+)?px$/);\n return matches ? Number(matches[1]) : undefined;\n }\n /**\n * Initializes the canvas style and render size without modifying the canvas display size,\n * since responsiveness is handled by the controller.resize() method. The config is used\n * to determine the aspect ratio to apply in case no explicit height has been specified.\n */\n\n\n function initCanvas(canvas, config) {\n var style = canvas.style; // NOTE(SB) canvas.getAttribute('width') !== canvas.width: in the first case it\n // returns null or '' if no explicit value has been set to the canvas attribute.\n\n var renderHeight = canvas.getAttribute('height');\n var renderWidth = canvas.getAttribute('width'); // Chart.js modifies some canvas values that we want to restore on destroy\n\n canvas[EXPANDO_KEY] = {\n initial: {\n height: renderHeight,\n width: renderWidth,\n style: {\n display: style.display,\n height: style.height,\n width: style.width\n }\n }\n }; // Force canvas to display as block to avoid extra space caused by inline\n // elements, which would interfere with the responsive resize process.\n // https://github.com/chartjs/Chart.js/issues/2538\n\n style.display = style.display || 'block';\n\n if (renderWidth === null || renderWidth === '') {\n var displayWidth = readUsedSize(canvas, 'width');\n\n if (displayWidth !== undefined) {\n canvas.width = displayWidth;\n }\n }\n\n if (renderHeight === null || renderHeight === '') {\n if (canvas.style.height === '') {\n // If no explicit render height and style height, let's apply the aspect ratio,\n // which one can be specified by the user but also by charts as default option\n // (i.e. options.aspectRatio). If not specified, use canvas aspect ratio of 2.\n canvas.height = canvas.width / (config.options.aspectRatio || 2);\n } else {\n var displayHeight = readUsedSize(canvas, 'height');\n\n if (displayWidth !== undefined) {\n canvas.height = displayHeight;\n }\n }\n }\n\n return canvas;\n }\n /**\n * Detects support for options object argument in addEventListener.\n * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support\n * @private\n */\n\n\n var supportsEventListenerOptions = function () {\n var supports = false;\n\n try {\n var options = Object.defineProperty({}, 'passive', {\n // eslint-disable-next-line getter-return\n get: function () {\n supports = true;\n }\n });\n window.addEventListener('e', null, options);\n } catch (e) {// continue regardless of error\n }\n\n return supports;\n }(); // Default passive to true as expected by Chrome for 'touchstart' and 'touchend' events.\n // https://github.com/chartjs/Chart.js/issues/4287\n\n\n var eventListenerOptions = supportsEventListenerOptions ? {\n passive: true\n } : false;\n\n function addListener(node, type, listener) {\n node.addEventListener(type, listener, eventListenerOptions);\n }\n\n function removeListener(node, type, listener) {\n node.removeEventListener(type, listener, eventListenerOptions);\n }\n\n function createEvent(type, chart, x, y, nativeEvent) {\n return {\n type: type,\n chart: chart,\n native: nativeEvent || null,\n x: x !== undefined ? x : null,\n y: y !== undefined ? y : null\n };\n }\n\n function fromNativeEvent(event, chart) {\n var type = EVENT_TYPES[event.type] || event.type;\n var pos = helpers$1.getRelativePosition(event, chart);\n return createEvent(type, chart, pos.x, pos.y, event);\n }\n\n function throttled(fn, thisArg) {\n var ticking = false;\n var args = [];\n return function () {\n args = Array.prototype.slice.call(arguments);\n thisArg = thisArg || this;\n\n if (!ticking) {\n ticking = true;\n helpers$1.requestAnimFrame.call(window, function () {\n ticking = false;\n fn.apply(thisArg, args);\n });\n }\n };\n }\n\n function createDiv(cls) {\n var el = document.createElement('div');\n el.className = cls || '';\n return el;\n } // Implementation based on https://github.com/marcj/css-element-queries\n\n\n function createResizer(handler) {\n var maxSize = 1000000; // NOTE(SB) Don't use innerHTML because it could be considered unsafe.\n // https://github.com/chartjs/Chart.js/issues/5902\n\n var resizer = createDiv(CSS_SIZE_MONITOR);\n var expand = createDiv(CSS_SIZE_MONITOR + '-expand');\n var shrink = createDiv(CSS_SIZE_MONITOR + '-shrink');\n expand.appendChild(createDiv());\n shrink.appendChild(createDiv());\n resizer.appendChild(expand);\n resizer.appendChild(shrink);\n\n resizer._reset = function () {\n expand.scrollLeft = maxSize;\n expand.scrollTop = maxSize;\n shrink.scrollLeft = maxSize;\n shrink.scrollTop = maxSize;\n };\n\n var onScroll = function () {\n resizer._reset();\n\n handler();\n };\n\n addListener(expand, 'scroll', onScroll.bind(expand, 'expand'));\n addListener(shrink, 'scroll', onScroll.bind(shrink, 'shrink'));\n return resizer;\n } // https://davidwalsh.name/detect-node-insertion\n\n\n function watchForRender(node, handler) {\n var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {});\n\n var proxy = expando.renderProxy = function (e) {\n if (e.animationName === CSS_RENDER_ANIMATION) {\n handler();\n }\n };\n\n helpers$1.each(ANIMATION_START_EVENTS, function (type) {\n addListener(node, type, proxy);\n }); // #4737: Chrome might skip the CSS animation when the CSS_RENDER_MONITOR class\n // is removed then added back immediately (same animation frame?). Accessing the\n // `offsetParent` property will force a reflow and re-evaluate the CSS animation.\n // https://gist.github.com/paulirish/5d52fb081b3570c81e3a#box-metrics\n // https://github.com/chartjs/Chart.js/issues/4737\n\n expando.reflow = !!node.offsetParent;\n node.classList.add(CSS_RENDER_MONITOR);\n }\n\n function unwatchForRender(node) {\n var expando = node[EXPANDO_KEY] || {};\n var proxy = expando.renderProxy;\n\n if (proxy) {\n helpers$1.each(ANIMATION_START_EVENTS, function (type) {\n removeListener(node, type, proxy);\n });\n delete expando.renderProxy;\n }\n\n node.classList.remove(CSS_RENDER_MONITOR);\n }\n\n function addResizeListener(node, listener, chart) {\n var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {}); // Let's keep track of this added resizer and thus avoid DOM query when removing it.\n\n var resizer = expando.resizer = createResizer(throttled(function () {\n if (expando.resizer) {\n var container = chart.options.maintainAspectRatio && node.parentNode;\n var w = container ? container.clientWidth : 0;\n listener(createEvent('resize', chart));\n\n if (container && container.clientWidth < w && chart.canvas) {\n // If the container size shrank during chart resize, let's assume\n // scrollbar appeared. So we resize again with the scrollbar visible -\n // effectively making chart smaller and the scrollbar hidden again.\n // Because we are inside `throttled`, and currently `ticking`, scroll\n // events are ignored during this whole 2 resize process.\n // If we assumed wrong and something else happened, we are resizing\n // twice in a frame (potential performance issue)\n listener(createEvent('resize', chart));\n }\n }\n })); // The resizer needs to be attached to the node parent, so we first need to be\n // sure that `node` is attached to the DOM before injecting the resizer element.\n\n watchForRender(node, function () {\n if (expando.resizer) {\n var container = node.parentNode;\n\n if (container && container !== resizer.parentNode) {\n container.insertBefore(resizer, container.firstChild);\n } // The container size might have changed, let's reset the resizer state.\n\n\n resizer._reset();\n }\n });\n }\n\n function removeResizeListener(node) {\n var expando = node[EXPANDO_KEY] || {};\n var resizer = expando.resizer;\n delete expando.resizer;\n unwatchForRender(node);\n\n if (resizer && resizer.parentNode) {\n resizer.parentNode.removeChild(resizer);\n }\n }\n /**\n * Injects CSS styles inline if the styles are not already present.\n * @param {HTMLDocument|ShadowRoot} rootNode - the node to contain the plotly-logomark '}};},{}],716:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';/**\n * Determine the position anchor property of x/y xanchor/yanchor components.\n *\n * - values < 1/3 align the low side at that fraction,\n * - values [1/3, 2/3] align the center at that fraction,\n * - values > 2/3 align the right at that fraction.\n */exports.isLeftAnchor=function isLeftAnchor(opts){return opts.xanchor==='left'||opts.xanchor==='auto'&&opts.x<=1/3;};exports.isCenterAnchor=function isCenterAnchor(opts){return opts.xanchor==='center'||opts.xanchor==='auto'&&opts.x>1/3&&opts.x<2/3;};exports.isRightAnchor=function isRightAnchor(opts){return opts.xanchor==='right'||opts.xanchor==='auto'&&opts.x>=2/3;};exports.isTopAnchor=function isTopAnchor(opts){return opts.yanchor==='top'||opts.yanchor==='auto'&&opts.y>=2/3;};exports.isMiddleAnchor=function isMiddleAnchor(opts){return opts.yanchor==='middle'||opts.yanchor==='auto'&&opts.y>1/3&&opts.y<2/3;};exports.isBottomAnchor=function isBottomAnchor(opts){return opts.yanchor==='bottom'||opts.yanchor==='auto'&&opts.y<=1/3;};},{}],717:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var modModule=_dereq_('./mod');var mod=modModule.mod;var modHalf=modModule.modHalf;var PI=Math.PI;var twoPI=2*PI;function deg2rad(deg){return deg/180*PI;}function rad2deg(rad){return rad/PI*180;}/**\n * is sector a full circle?\n * ... this comes up a lot in SVG path-drawing routines\n *\n * N.B. we consider all sectors that span more that 2pi 'full' circles\n *\n * @param {2-item array} aBnds : angular bounds in *radians*\n * @return {boolean}\n */function isFullCircle(aBnds){return Math.abs(aBnds[1]-aBnds[0])>twoPI-1e-14;}/**\n * angular delta between angle 'a' and 'b'\n * solution taken from: https://stackoverflow.com/a/2007279\n *\n * @param {number} a : first angle in *radians*\n * @param {number} b : second angle in *radians*\n * @return {number} angular delta in *radians*\n */function angleDelta(a,b){return modHalf(b-a,twoPI);}/**\n * angular distance between angle 'a' and 'b'\n *\n * @param {number} a : first angle in *radians*\n * @param {number} b : second angle in *radians*\n * @return {number} angular distance in *radians*\n */function angleDist(a,b){return Math.abs(angleDelta(a,b));}/**\n * is angle inside sector?\n *\n * @param {number} a : angle to test in *radians*\n * @param {2-item array} aBnds : sector's angular bounds in *radians*\n * @param {boolean}\n */function isAngleInsideSector(a,aBnds){if(isFullCircle(aBnds))return true;var s0,s1;if(aBnds[0]s1)s1+=twoPI;var a0=mod(a,twoPI);var a1=a0+twoPI;return a0>=s0&&a0<=s1||a1>=s0&&a1<=s1;}/**\n * is pt (r,a) inside sector?\n *\n * @param {number} r : pt's radial coordinate\n * @param {number} a : pt's angular coordinate in *radians*\n * @param {2-item array} rBnds : sector's radial bounds\n * @param {2-item array} aBnds : sector's angular bounds in *radians*\n * @return {boolean}\n */function isPtInsideSector(r,a,rBnds,aBnds){if(!isAngleInsideSector(a,aBnds))return false;var r0,r1;if(rBnds[0]=r0&&r<=r1;}// common to pathArc, pathSector and pathAnnulus\nfunction _path(r0,r1,a0,a1,cx,cy,isClosed){cx=cx||0;cy=cy||0;var isCircle=isFullCircle([a0,a1]);var aStart,aMid,aEnd;var rStart,rEnd;if(isCircle){aStart=0;aMid=PI;aEnd=twoPI;}else{if(a0opts.max){propOut.set(dflt);}else propOut.set(+v);}},integer:{coerceFunction:function(v,propOut,dflt,opts){if(v%1||!isNumeric(v)||opts.min!==undefined&&vopts.max){propOut.set(dflt);}else propOut.set(+v);}},string:{// TODO 'values shouldn't be in there (edge case: 'dash' in Scatter)\ncoerceFunction:function(v,propOut,dflt,opts){if(typeof v!=='string'){var okToCoerce=typeof v==='number';if(opts.strict===true||!okToCoerce)propOut.set(dflt);else propOut.set(String(v));}else if(opts.noBlank&&!v)propOut.set(dflt);else propOut.set(v);}},color:{coerceFunction:function(v,propOut,dflt){if(tinycolor(v).isValid())propOut.set(v);else propOut.set(dflt);}},colorlist:{coerceFunction:function(v,propOut,dflt){function isColor(color){return tinycolor(color).isValid();}if(!Array.isArray(v)||!v.length)propOut.set(dflt);else if(v.every(isColor))propOut.set(v);else propOut.set(dflt);}},colorscale:{coerceFunction:function(v,propOut,dflt){propOut.set(colorscales.get(v,dflt));}},angle:{coerceFunction:function(v,propOut,dflt){if(v==='auto')propOut.set('auto');else if(!isNumeric(v))propOut.set(dflt);else propOut.set(modHalf(+v,360));}},subplotid:{coerceFunction:function(v,propOut,dflt,opts){var regex=opts.regex||counterRegex(dflt);if(typeof v==='string'&®ex.test(v)){propOut.set(v);return;}propOut.set(dflt);},validateFunction:function(v,opts){var dflt=opts.dflt;if(v===dflt)return true;if(typeof v!=='string')return false;if(counterRegex(dflt).test(v))return true;return false;}},flaglist:{coerceFunction:function(v,propOut,dflt,opts){if(typeof v!=='string'){propOut.set(dflt);return;}if((opts.extras||[]).indexOf(v)!==-1){propOut.set(v);return;}var vParts=v.split('+');var i=0;while(iHH:MM:SS.sss?\n *\n * : space (our normal standard) or T or t (ISO-8601)\n * : Z, z, or [+\\-]HH:?MM and we THROW IT AWAY\n * this format comes from https://tools.ietf.org/html/rfc3339#section-5.6\n * but we allow it even with a space as the separator\n *\n * May truncate after any full field, and sss can be any length\n * even >3 digits, though javascript dates truncate to milliseconds,\n * we keep as much as javascript numeric precision can hold, but we only\n * report back up to 100 microsecond precision, because most dates support\n * this precision (close to 1970 support more, very far away support less)\n *\n * Expanded to support negative years to -9999 but you must always\n * give 4 digits, except for 2-digit positive years which we assume are\n * near the present time.\n * Note that we follow ISO 8601:2004: there *is* a year 0, which\n * is 1BC/BCE, and -1===2BC etc.\n *\n * World calendars: not all of these *have* agreed extensions to this full range,\n * if you have another calendar system but want a date range outside its validity,\n * you can use a gregorian date string prefixed with 'G' or 'g'.\n *\n * Where to cut off 2-digit years between 1900s and 2000s?\n * from http://support.microsoft.com/kb/244664:\n * 1930-2029 (the most retro of all...)\n * but in my mac chrome from eg. d=new Date(Date.parse('8/19/50')):\n * 1950-2049\n * by Java, from http://stackoverflow.com/questions/2024273/:\n * now-80 - now+19\n * or FileMaker Pro, from\n * http://www.filemaker.com/12help/html/add_view_data.4.21.html:\n * now-70 - now+29\n * but python strptime etc, via\n * http://docs.python.org/py3k/library/time.html:\n * 1969-2068 (super forward-looking, but static, not sliding!)\n *\n * lets go with now-70 to now+29, and if anyone runs into this problem\n * they can learn the hard way not to use 2-digit years, as no choice we\n * make now will cover all possibilities. mostly this will all be taken\n * care of in initial parsing, should only be an issue for hand-entered data\n * currently (2016) this range is:\n * 1946-2045\n */exports.dateTime2ms=function(s,calendar){// first check if s is a date object\nif(exports.isJSDate(s)){// Convert to the UTC milliseconds that give the same\n// hours as this date has in the local timezone\nvar tzOffset=s.getTimezoneOffset()*ONEMIN;var offsetTweak=(s.getUTCMinutes()-s.getMinutes())*ONEMIN+(s.getUTCSeconds()-s.getSeconds())*ONESEC+(s.getUTCMilliseconds()-s.getMilliseconds());if(offsetTweak){var comb=3*ONEMIN;tzOffset=tzOffset-comb/2+mod(offsetTweak-tzOffset+comb/2,comb);}s=Number(s)-tzOffset;if(s>=MIN_MS&&s<=MAX_MS)return s;return BADNUM;}// otherwise only accept strings and numbers\nif(typeof s!=='string'&&typeof s!=='number')return BADNUM;s=String(s);var isWorld=isWorldCalendar(calendar);// to handle out-of-range dates in international calendars, accept\n// 'G' as a prefix to force the built-in gregorian calendar.\nvar s0=s.charAt(0);if(isWorld&&(s0==='G'||s0==='g')){s=s.substr(1);calendar='';}var isChinese=isWorld&&calendar.substr(0,7)==='chinese';var match=s.match(isChinese?DATETIME_REGEXP_CN:DATETIME_REGEXP);if(!match)return BADNUM;var y=match[1];var m=match[3]||'1';var d=Number(match[5]||1);var H=Number(match[7]||0);var M=Number(match[9]||0);var S=Number(match[11]||0);if(isWorld){// disallow 2-digit years for world calendars\nif(y.length===2)return BADNUM;y=Number(y);var cDate;try{var calInstance=Registry.getComponentMethod('calendars','getCal')(calendar);if(isChinese){var isIntercalary=m.charAt(m.length-1)==='i';m=parseInt(m,10);cDate=calInstance.newDate(y,calInstance.toMonthIndex(y,m,isIntercalary),d);}else{cDate=calInstance.newDate(y,Number(m),d);}}catch(e){return BADNUM;}// Invalid ... date\nif(!cDate)return BADNUM;return(cDate.toJD()-EPOCHJD)*ONEDAY+H*ONEHOUR+M*ONEMIN+S*ONESEC;}if(y.length===2){y=(Number(y)+2000-YFIRST)%100+YFIRST;}else y=Number(y);// new Date uses months from 0; subtract 1 here just so we\n// don't have to do it again during the validity test below\nm-=1;// javascript takes new Date(0..99,m,d) to mean 1900-1999, so\n// to support years 0-99 we need to use setFullYear explicitly\n// Note that 2000 is a leap year.\nvar date=new Date(Date.UTC(2000,m,d,H,M));date.setUTCFullYear(y);if(date.getUTCMonth()!==m)return BADNUM;if(date.getUTCDate()!==d)return BADNUM;return date.getTime()+S*ONESEC;};MIN_MS=exports.MIN_MS=exports.dateTime2ms('-9999');MAX_MS=exports.MAX_MS=exports.dateTime2ms('9999-12-31 23:59:59.9999');// is string s a date? (see above)\nexports.isDateTime=function(s,calendar){return exports.dateTime2ms(s,calendar)!==BADNUM;};// pad a number with zeroes, to given # of digits before the decimal point\nfunction lpad(val,digits){return String(val+Math.pow(10,digits)).substr(1);}/**\n * Turn ms into string of the form YYYY-mm-dd HH:MM:SS.ssss\n * Crop any trailing zeros in time, except never stop right after hours\n * (we could choose to crop '-01' from date too but for now we always\n * show the whole date)\n * Optional range r is the data range that applies, also in ms.\n * If rng is big, the later parts of time will be omitted\n */var NINETYDAYS=90*ONEDAY;var THREEHOURS=3*ONEHOUR;var FIVEMIN=5*ONEMIN;exports.ms2DateTime=function(ms,r,calendar){if(typeof ms!=='number'||!(ms>=MIN_MS&&ms<=MAX_MS))return BADNUM;if(!r)r=0;var msecTenths=Math.floor(mod(ms+0.05,1)*10);var msRounded=Math.round(ms-msecTenths/10);var dateStr,h,m,s,msec10,d;if(isWorldCalendar(calendar)){var dateJD=Math.floor(msRounded/ONEDAY)+EPOCHJD;var timeMs=Math.floor(mod(ms,ONEDAY));try{dateStr=Registry.getComponentMethod('calendars','getCal')(calendar).fromJD(dateJD).formatDate('yyyy-mm-dd');}catch(e){// invalid date in this calendar - fall back to Gyyyy-mm-dd\ndateStr=utcFormat('G%Y-%m-%d')(new Date(msRounded));}// yyyy does NOT guarantee 4-digit years. YYYY mostly does, but does\n// other things for a few calendars, so we can't trust it. Just pad\n// it manually (after the '-' if there is one)\nif(dateStr.charAt(0)==='-'){while(dateStr.length<11)dateStr='-0'+dateStr.substr(1);}else{while(dateStr.length<10)dateStr='0'+dateStr;}// TODO: if this is faster, we could use this block for extracting\n// the time components of regular gregorian too\nh=r=MIN_MS+ONEDAY&&ms<=MAX_MS-ONEDAY))return BADNUM;var msecTenths=Math.floor(mod(ms+0.05,1)*10);var d=new Date(Math.round(ms-msecTenths/10));var dateStr=d3.time.format('%Y-%m-%d')(d);var h=d.getHours();var m=d.getMinutes();var s=d.getSeconds();var msec10=d.getUTCMilliseconds()*10+msecTenths;return includeTime(dateStr,h,m,s,msec10);};function includeTime(dateStr,h,m,s,msec10){// include each part that has nonzero data in or after it\nif(h||m||s||msec10){dateStr+=' '+lpad(h,2)+':'+lpad(m,2);if(s||msec10){dateStr+=':'+lpad(s,2);if(msec10){var digits=4;while(msec10%10===0){digits-=1;msec10/=10;}dateStr+='.'+lpad(msec10,digits);}}}return dateStr;}// normalize date format to date string, in case it starts as\n// a Date object or milliseconds\n// optional dflt is the return value if cleaning fails\nexports.cleanDate=function(v,dflt,calendar){// let us use cleanDate to provide a missing default without an error\nif(v===BADNUM)return dflt;if(exports.isJSDate(v)||typeof v==='number'&&isFinite(v)){// do not allow milliseconds (old) or jsdate objects (inherently\n// described as gregorian dates) with world calendars\nif(isWorldCalendar(calendar)){Loggers.error('JS Dates and milliseconds are incompatible with world calendars',v);return dflt;}// NOTE: if someone puts in a year as a number rather than a string,\n// this will mistakenly convert it thinking it's milliseconds from 1970\n// that is: '2012' -> Jan. 1, 2012, but 2012 -> 2012 epoch milliseconds\nv=exports.ms2DateTimeLocal(+v);if(!v&&dflt!==undefined)return dflt;}else if(!exports.isDateTime(v,calendar)){Loggers.error('unrecognized date',v);return dflt;}return v;};/*\n * Date formatting for ticks and hovertext\n */ /*\n * modDateFormat: Support world calendars, and add one item to\n * d3's vocabulary:\n * %{n}f where n is the max number of digits of fractional seconds\n */var fracMatch=/%\\d?f/g;function modDateFormat(fmt,x,formatter,calendar){fmt=fmt.replace(fracMatch,function(match){var digits=Math.min(+match.charAt(1)||6,6);var fracSecs=(x/1000%1+2).toFixed(digits).substr(2).replace(/0+$/,'')||'0';return fracSecs;});var d=new Date(Math.floor(x+0.05));if(isWorldCalendar(calendar)){try{fmt=Registry.getComponentMethod('calendars','worldCalFmt')(fmt,x,calendar);}catch(e){return'Invalid';}}return formatter(fmt)(d);}/*\n * formatTime: create a time string from:\n * x: milliseconds\n * tr: tickround ('M', 'S', or # digits)\n * only supports UTC times (where every day is 24 hours and 0 is at midnight)\n */var MAXSECONDS=[59,59.9,59.99,59.999,59.9999];function formatTime(x,tr){var timePart=mod(x+0.05,ONEDAY);var timeStr=lpad(Math.floor(timePart/ONEHOUR),2)+':'+lpad(mod(Math.floor(timePart/ONEMIN),60),2);if(tr!=='M'){if(!isNumeric(tr))tr=0;// should only be 'S'\n/*\n * this is a weird one - and shouldn't come up unless people\n * monkey with tick0 in weird ways, but we need to do something!\n * IN PARTICULAR we had better not display garbage (see below)\n * for numbers we always round to the nearest increment of the\n * precision we're showing, and this seems like the right way to\n * handle seconds and milliseconds, as they have a decimal point\n * and people will interpret that to mean rounding like numbers.\n * but for larger increments we floor the value: it's always\n * 2013 until the ball drops on the new year. We could argue about\n * which field it is where we start rounding (should 12:08:59\n * round to 12:09 if we're stopping at minutes?) but for now I'll\n * say we round seconds but floor everything else. BUT that means\n * we need to never round up to 60 seconds, ie 23:59:60\n */var sec=Math.min(mod(x/ONESEC,60),MAXSECONDS[tr]);var secStr=(100+sec).toFixed(tr).substr(1);if(tr>0){secStr=secStr.replace(/0+$/,'').replace(/[\\.]$/,'');}timeStr+=':'+secStr;}return timeStr;}/*\n * formatDate: turn a date into tick or hover label text.\n *\n * x: milliseconds, the value to convert\n * fmt: optional, an explicit format string (d3 format, even for world calendars)\n * tr: tickround ('y', 'm', 'd', 'M', 'S', or # digits)\n * used if no explicit fmt is provided\n * formatter: locale-aware d3 date formatter for standard gregorian calendars\n * should be the result of exports.getD3DateFormat(gd)\n * calendar: optional string, the world calendar system to use\n *\n * returns the date/time as a string, potentially with the leading portion\n * on a separate line (after '\\n')\n * Note that this means if you provide an explicit format which includes '\\n'\n * the axis may choose to strip things after it when they don't change from\n * one tick to the next (as it does with automatic formatting)\n */exports.formatDate=function(x,fmt,tr,formatter,calendar,extraFormat){calendar=isWorldCalendar(calendar)&&calendar;if(!fmt){if(tr==='y')fmt=extraFormat.year;else if(tr==='m')fmt=extraFormat.month;else if(tr==='d'){fmt=extraFormat.dayMonth+'\\n'+extraFormat.year;}else{return formatTime(x,tr)+'\\n'+modDateFormat(extraFormat.dayMonthYear,x,formatter,calendar);}}return modDateFormat(fmt,x,formatter,calendar);};/*\n * incrementMonth: make a new milliseconds value from the given one,\n * having changed the month\n *\n * special case for world calendars: multiples of 12 are treated as years,\n * even for calendar systems that don't have (always or ever) 12 months/year\n * TODO: perhaps we need a different code for year increments to support this?\n *\n * ms (number): the initial millisecond value\n * dMonth (int): the (signed) number of months to shift\n * calendar (string): the calendar system to use\n *\n * changing month does not (and CANNOT) always preserve day, since\n * months have different lengths. The worst example of this is:\n * d = new Date(1970,0,31); d.setMonth(1) -> Feb 31 turns into Mar 3\n *\n * But we want to be able to iterate over the last day of each month,\n * regardless of what its number is.\n * So shift 3 days forward, THEN set the new month, then unshift:\n * 1/31 -> 2/28 (or 29) -> 3/31 -> 4/30 -> ...\n *\n * Note that odd behavior still exists if you start from the 26th-28th:\n * 1/28 -> 2/28 -> 3/31\n * but at least you can't shift any dates into the wrong month,\n * and ticks on these days incrementing by month would be very unusual\n */var THREEDAYS=3*ONEDAY;exports.incrementMonth=function(ms,dMonth,calendar){calendar=isWorldCalendar(calendar)&&calendar;// pull time out and operate on pure dates, then add time back at the end\n// this gives maximum precision - not that we *normally* care if we're\n// incrementing by month, but better to be safe!\nvar timeMs=mod(ms,ONEDAY);ms=Math.round(ms-timeMs);if(calendar){try{var dateJD=Math.round(ms/ONEDAY)+EPOCHJD;var calInstance=Registry.getComponentMethod('calendars','getCal')(calendar);var cDate=calInstance.fromJD(dateJD);if(dMonth%12)calInstance.add(cDate,dMonth,'m');else calInstance.add(cDate,dMonth/12,'y');return(cDate.toJD()-EPOCHJD)*ONEDAY+timeMs;}catch(e){Loggers.error('invalid ms '+ms+' in calendar '+calendar);// then keep going in gregorian even though the result will be 'Invalid'\n}}var y=new Date(ms+THREEDAYS);return y.setUTCMonth(y.getUTCMonth()+dMonth)+timeMs-THREEDAYS;};/*\n * findExactDates: what fraction of data is exact days, months, or years?\n *\n * data: array of millisecond values\n * calendar (string) the calendar to test against\n */exports.findExactDates=function(data,calendar){var exactYears=0;var exactMonths=0;var exactDays=0;var blankCount=0;var d;var di;var calInstance=isWorldCalendar(calendar)&&Registry.getComponentMethod('calendars','getCal')(calendar);for(var i=0;i deep extend) first argument,\n * use `extendFlat` for first-level only extend and\n * use `extendDeep` for a deep extend.\n *\n * Other differences with jQuery version:\n * - Uses a modern (and faster) isPlainObject routine.\n * - Expected to work with object {} and array [] arguments only.\n * - Does not check for circular structure.\n * FYI: jQuery only does a check across one level.\n * Warning: this might result in infinite loops.\n *\n */function _extend(inputs,isDeep,keepAllKeys,noArrayCopies){var target=inputs[0];var length=inputs.length;var input,key,src,copy,copyIsArray,clone,allPrimitives;// TODO does this do the right thing for typed arrays?\nif(length===2&&isArray(target)&&isArray(inputs[1])&&target.length===0){allPrimitives=primitivesLoopSplice(inputs[1],target);if(allPrimitives){return target;}else{target.splice(0,target.length);// reset target and continue to next block\n}}for(var i=1;i0&&pts[l+1][0]<0)return l;}return null;}if(loc==='RUS'||loc==='FJI'){// Russia and Fiji have landmasses that cross the antimeridian,\n// we need to add +360 to their longitude coordinates, so that\n// polygon 'contains' doesn't get confused when crossing the antimeridian.\n//\n// Note that other countries have polygons on either side of the antimeridian\n// (e.g. some Aleutian island for the USA), but those don't confuse\n// the 'contains' method; these are skipped here.\nappendPolygon=function(_pts){var pts;if(doesCrossAntiMerdian(_pts)===null){pts=_pts;}else{pts=new Array(_pts.length);for(m=0;m<_pts.length;m++){// do not mutate calcdata[i][j].geojson !!\npts[m]=[_pts[m][0]<0?_pts[m][0]+360:_pts[m][0],_pts[m][1]];}}polygons.push(polygon.tester(pts));};}else if(loc==='ATA'){// Antarctica has a landmass that wraps around every longitudes which\n// confuses the 'contains' methods.\nappendPolygon=function(pts){var crossAntiMeridianIndex=doesCrossAntiMerdian(pts);// polygon that do not cross anti-meridian need no special handling\nif(crossAntiMeridianIndex===null){return polygons.push(polygon.tester(pts));}// stitch polygon by adding pt over South Pole,\n// so that it covers the projected region covers all latitudes\n//\n// Note that the algorithm below only works for polygons that\n// start and end on longitude -180 (like the ones built by\n// https://github.com/etpinard/sane-topojson).\nvar stitch=new Array(pts.length+1);var si=0;for(m=0;mcrossAntiMeridianIndex){stitch[si++]=[pts[m][0]+360,pts[m][1]];}else if(m===crossAntiMeridianIndex){stitch[si++]=pts[m];stitch[si++]=[pts[m][0],-90];}else{stitch[si++]=pts[m];}}// polygon.tester by default appends pt[0] to the points list,\n// we must remove it here, to avoid a jump in longitude from 180 to -180,\n// that would confuse the 'contains' method\nvar tester=polygon.tester(stitch);tester.pts.pop();polygons.push(tester);};}else{// otherwise using same array ref is fine\nappendPolygon=function(pts){polygons.push(polygon.tester(pts));};}switch(geometry.type){case'MultiPolygon':for(j=0;jmaxArea){maxArea=area;poly=polyi;}}}else{poly=geometry;}return turfCentroid.default(poly).geometry.coordinates;}function fetchTraceGeoData(calcData){var PlotlyGeoAssets=window.PlotlyGeoAssets||{};var promises=[];function fetch(url){return new Promise(function(resolve,reject){d3.json(url,function(err,d){if(err){delete PlotlyGeoAssets[url];var msg=err.status===404?'GeoJSON at URL \"'+url+'\" does not exist.':'Unexpected error while fetching from '+url;return reject(new Error(msg));}PlotlyGeoAssets[url]=d;return resolve(d);});});}function wait(url){return new Promise(function(resolve,reject){var cnt=0;var interval=setInterval(function(){if(PlotlyGeoAssets[url]&&PlotlyGeoAssets[url]!=='pending'){clearInterval(interval);return resolve(PlotlyGeoAssets[url]);}if(cnt>100){clearInterval(interval);return reject('Unexpected error while fetching from '+url);}cnt++;},50);});}for(var i=0;i0){coords.push(lineString);lineString=[];}}if(lineString.length>0){coords.push(lineString);}return coords;};/**\n * Make line ('LineString' or 'MultiLineString') GeoJSON\n *\n * @param {array} coords\n * results form calcTraceToLineCoords\n * @return {object} out\n * GeoJSON object\n *\n */exports.makeLine=function(coords){if(coords.length===1){return{type:'LineString',coordinates:coords[0]};}else{return{type:'MultiLineString',coordinates:coords};}};/**\n * Make polygon ('Polygon' or 'MultiPolygon') GeoJSON\n *\n * @param {array} coords\n * results form calcTraceToLineCoords\n * @return {object} out\n * GeoJSON object\n */exports.makePolygon=function(coords){if(coords.length===1){return{type:'Polygon',coordinates:coords};}else{var _coords=new Array(coords.length);for(var i=0;i2 and 3->4) - returns array [x,y] if they do, null if not\n */exports.segmentsIntersect=segmentsIntersect;function segmentsIntersect(x1,y1,x2,y2,x3,y3,x4,y4){var a=x2-x1;var b=x3-x1;var c=x4-x3;var d=y2-y1;var e=y3-y1;var f=y4-y3;var det=a*f-c*d;// parallel lines? intersection is undefined\n// ignore the case where they are colinear\nif(det===0)return null;var t=(b*f-c*e)/det;var u=(b*d-a*e)/det;// segments do not intersect?\nif(u<0||u>1||t<0||t>1)return null;return{x:x1+a*t,y:y1+d*t};}/*\n * find the minimum distance between two line segments (1->2 and 3->4)\n */exports.segmentDistance=function segmentDistance(x1,y1,x2,y2,x3,y3,x4,y4){if(segmentsIntersect(x1,y1,x2,y2,x3,y3,x4,y4))return 0;// the two segments and their lengths squared\nvar x12=x2-x1;var y12=y2-y1;var x34=x4-x3;var y34=y4-y3;var ll12=x12*x12+y12*y12;var ll34=x34*x34+y34*y34;// calculate distance squared, then take the sqrt at the very end\nvar dist2=Math.min(perpDistance2(x12,y12,ll12,x3-x1,y3-y1),perpDistance2(x12,y12,ll12,x4-x1,y4-y1),perpDistance2(x34,y34,ll34,x1-x3,y1-y3),perpDistance2(x34,y34,ll34,x2-x3,y2-y3));return Math.sqrt(dist2);};/*\n * distance squared from segment ab to point c\n * [xab, yab] is the vector b-a\n * [xac, yac] is the vector c-a\n * llab is the length squared of (b-a), just to simplify calculation\n */function perpDistance2(xab,yab,llab,xac,yac){var fcAB=xac*xab+yac*yab;if(fcAB<0){// point c is closer to point a\nreturn xac*xac+yac*yac;}else if(fcAB>llab){// point c is closer to point b\nvar xbc=xac-xab;var ybc=yac-yab;return xbc*xbc+ybc*ybc;}else{// perpendicular distance is the shortest\nvar crossProduct=xac*yab-yac*xab;return crossProduct*crossProduct/llab;}}// a very short-term cache for getTextLocation, just because\n// we're often looping over the same locations multiple times\n// invalidated as soon as we look at a different path\nvar locationCache,workingPath,workingTextWidth;// turn a path and position along it into x, y, and angle for the given text\nexports.getTextLocation=function getTextLocation(path,totalPathLen,positionOnPath,textWidth){if(path!==workingPath||textWidth!==workingTextWidth){locationCache={};workingPath=path;workingTextWidth=textWidth;}if(locationCache[positionOnPath]){return locationCache[positionOnPath];}// for the angle, use points on the path separated by the text width\n// even though due to curvature, the text will cover a bit more than that\nvar p0=path.getPointAtLength(mod(positionOnPath-textWidth/2,totalPathLen));var p1=path.getPointAtLength(mod(positionOnPath+textWidth/2,totalPathLen));// note: atan handles 1/0 nicely\nvar theta=Math.atan((p1.y-p0.y)/(p1.x-p0.x));// center the text at 2/3 of the center position plus 1/3 the p0/p1 midpoint\n// that's the average position of this segment, assuming it's roughly quadratic\nvar pCenter=path.getPointAtLength(mod(positionOnPath,totalPathLen));var x=(pCenter.x*4+p0.x+p1.x)/6;var y=(pCenter.y*4+p0.y+p1.y)/6;var out={x:x,y:y,theta:theta};locationCache[positionOnPath]=out;return out;};exports.clearLocationCache=function(){workingPath=null;};/*\n * Find the segment of `path` that's within the visible area\n * given by `bounds` {left, right, top, bottom}, to within a\n * precision of `buffer` px\n *\n * returns: undefined if nothing is visible, else object:\n * {\n * min: position where the path first enters bounds, or 0 if it\n * starts within bounds\n * max: position where the path last exits bounds, or the path length\n * if it finishes within bounds\n * len: max - min, ie the length of visible path\n * total: the total path length - just included so the caller doesn't\n * need to call path.getTotalLength() again\n * isClosed: true iff the start and end points of the path are both visible\n * and are at the same point\n * }\n *\n * Works by starting from either end and repeatedly finding the distance from\n * that point to the plot area, and if it's outside the plot, moving along the\n * path by that distance (because the plot must be at least that far away on\n * the path). Note that if a path enters, exits, and re-enters the plot, we\n * will not capture this behavior.\n */exports.getVisibleSegment=function getVisibleSegment(path,bounds,buffer){var left=bounds.left;var right=bounds.right;var top=bounds.top;var bottom=bounds.bottom;var pMin=0;var pTotal=path.getTotalLength();var pMax=pTotal;var pt0,ptTotal;function getDistToPlot(len){var pt=path.getPointAtLength(len);// hold on to the start and end points for `closed`\nif(len===0)pt0=pt;else if(len===pTotal)ptTotal=pt;var dx=pt.xright?pt.x-right:0;var dy=pt.ybottom?pt.y-bottom:0;return Math.sqrt(dx*dx+dy*dy);}var distToPlot=getDistToPlot(pMin);while(distToPlot){pMin+=distToPlot+buffer;if(pMin>pMax)return;distToPlot=getDistToPlot(pMin);}distToPlot=getDistToPlot(pMax);while(distToPlot){pMax-=distToPlot+buffer;if(pMin>pMax)return;distToPlot=getDistToPlot(pMax);}return{min:pMin,max:pMax,len:pMax-pMin,total:pTotal,isClosed:pMin===0&&pMax===pTotal&&Math.abs(pt0.x-ptTotal.x)<0.1&&Math.abs(pt0.y-ptTotal.y)<0.1};};/**\n * Find point on SVG path corresponding to a given constraint coordinate\n *\n * @param {SVGPathElement} path\n * @param {Number} val : constraint coordinate value\n * @param {String} coord : 'x' or 'y' the constraint coordinate\n * @param {Object} opts :\n * - {Number} pathLength : supply total path length before hand\n * - {Number} tolerance\n * - {Number} iterationLimit\n * @return {SVGPoint}\n */exports.findPointOnPath=function findPointOnPath(path,val,coord,opts){opts=opts||{};var pathLength=opts.pathLength||path.getTotalLength();var tolerance=opts.tolerance||1e-3;var iterationLimit=opts.iterationLimit||30;// if path starts at a val greater than the path tail (like on vertical violins),\n// we must flip the sign of the computed diff.\nvar mul=path.getPointAtLength(0)[coord]>path.getPointAtLength(pathLength)[coord]?-1:1;var i=0;var b0=0;var b1=pathLength;var mid;var pt;var diff;while(i0){b1=mid;}else{b0=mid;}i++;}}return pt;};},{\"./mod\":742}],732:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var isNumeric=_dereq_('fast-isnumeric');var tinycolor=_dereq_('tinycolor2');var rgba=_dereq_('color-normalize');var Colorscale=_dereq_('../components/colorscale');var colorDflt=_dereq_('../components/color/attributes').defaultLine;var isArrayOrTypedArray=_dereq_('./array').isArrayOrTypedArray;var colorDfltRgba=rgba(colorDflt);var opacityDflt=1;function calculateColor(colorIn,opacityIn){var colorOut=colorIn;colorOut[3]*=opacityIn;return colorOut;}function validateColor(colorIn){if(isNumeric(colorIn))return colorDfltRgba;var colorOut=rgba(colorIn);return colorOut.length?colorOut:colorDfltRgba;}function validateOpacity(opacityIn){return isNumeric(opacityIn)?opacityIn:opacityDflt;}function formatColor(containerIn,opacityIn,len){var colorIn=containerIn.color;var isArrayColorIn=isArrayOrTypedArray(colorIn);var isArrayOpacityIn=isArrayOrTypedArray(opacityIn);var cOpts=Colorscale.extractOpts(containerIn);var colorOut=[];var sclFunc,getColor,getOpacity,colori,opacityi;if(cOpts.colorscale!==undefined){sclFunc=Colorscale.makeColorScaleFuncFromTrace(containerIn);}else{sclFunc=validateColor;}if(isArrayColorIn){getColor=function(c,i){// FIXME: there is double work, considering that sclFunc does the opposite\nreturn c[i]===undefined?colorDfltRgba:rgba(sclFunc(c[i]));};}else getColor=validateColor;if(isArrayOpacityIn){getOpacity=function(o,i){return o[i]===undefined?opacityDflt:validateOpacity(o[i]);};}else getOpacity=validateOpacity;if(isArrayColorIn||isArrayOpacityIn){for(var i=0;i` element need\n// access to the same data, or a `descend`, which fans a scenegraph node into a bunch of\n// of elements, e.g. points, lines, rows, requiring an array as input.\n// The role of the `keyFun` is to identify what elements are being entered/exited/updated,\n// otherwise D3 reverts to using a plain index which would screw up `transition`s.\nkeyFun:function(d){return d.key;},repeat:wrap,descend:identity,// Plotly.js uses a convention of storing the actual contents of the `calcData` as the\n// element zero of a container array. These helpers are just used for clarity as a\n// newcomer to the codebase may not know what the `[0]` is, and whether there can be further\n// elements (not atm).\nwrap:wrap,unwrap:function(d){return d[0];}};},{\"./identity\":734}],734:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';// Simple helper functions\n// none of these need any external deps\nmodule.exports=function identity(d){return d;};},{}],735:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var d3=_dereq_('d3');var isNumeric=_dereq_('fast-isnumeric');var numConstants=_dereq_('../constants/numerical');var FP_SAFE=numConstants.FP_SAFE;var BADNUM=numConstants.BADNUM;var lib=module.exports={};lib.nestedProperty=_dereq_('./nested_property');lib.keyedContainer=_dereq_('./keyed_container');lib.relativeAttr=_dereq_('./relative_attr');lib.isPlainObject=_dereq_('./is_plain_object');lib.toLogRange=_dereq_('./to_log_range');lib.relinkPrivateKeys=_dereq_('./relink_private');var arrayModule=_dereq_('./array');lib.isTypedArray=arrayModule.isTypedArray;lib.isArrayOrTypedArray=arrayModule.isArrayOrTypedArray;lib.isArray1D=arrayModule.isArray1D;lib.ensureArray=arrayModule.ensureArray;lib.concat=arrayModule.concat;lib.maxRowLength=arrayModule.maxRowLength;lib.minRowLength=arrayModule.minRowLength;var modModule=_dereq_('./mod');lib.mod=modModule.mod;lib.modHalf=modModule.modHalf;var coerceModule=_dereq_('./coerce');lib.valObjectMeta=coerceModule.valObjectMeta;lib.coerce=coerceModule.coerce;lib.coerce2=coerceModule.coerce2;lib.coerceFont=coerceModule.coerceFont;lib.coerceHoverinfo=coerceModule.coerceHoverinfo;lib.coerceSelectionMarkerOpacity=coerceModule.coerceSelectionMarkerOpacity;lib.validate=coerceModule.validate;var datesModule=_dereq_('./dates');lib.dateTime2ms=datesModule.dateTime2ms;lib.isDateTime=datesModule.isDateTime;lib.ms2DateTime=datesModule.ms2DateTime;lib.ms2DateTimeLocal=datesModule.ms2DateTimeLocal;lib.cleanDate=datesModule.cleanDate;lib.isJSDate=datesModule.isJSDate;lib.formatDate=datesModule.formatDate;lib.incrementMonth=datesModule.incrementMonth;lib.dateTick0=datesModule.dateTick0;lib.dfltRange=datesModule.dfltRange;lib.findExactDates=datesModule.findExactDates;lib.MIN_MS=datesModule.MIN_MS;lib.MAX_MS=datesModule.MAX_MS;var searchModule=_dereq_('./search');lib.findBin=searchModule.findBin;lib.sorterAsc=searchModule.sorterAsc;lib.sorterDes=searchModule.sorterDes;lib.distinctVals=searchModule.distinctVals;lib.roundUp=searchModule.roundUp;lib.sort=searchModule.sort;lib.findIndexOfMin=searchModule.findIndexOfMin;var statsModule=_dereq_('./stats');lib.aggNums=statsModule.aggNums;lib.len=statsModule.len;lib.mean=statsModule.mean;lib.median=statsModule.median;lib.midRange=statsModule.midRange;lib.variance=statsModule.variance;lib.stdev=statsModule.stdev;lib.interp=statsModule.interp;var matrixModule=_dereq_('./matrix');lib.init2dArray=matrixModule.init2dArray;lib.transposeRagged=matrixModule.transposeRagged;lib.dot=matrixModule.dot;lib.translationMatrix=matrixModule.translationMatrix;lib.rotationMatrix=matrixModule.rotationMatrix;lib.rotationXYMatrix=matrixModule.rotationXYMatrix;lib.apply2DTransform=matrixModule.apply2DTransform;lib.apply2DTransform2=matrixModule.apply2DTransform2;var anglesModule=_dereq_('./angles');lib.deg2rad=anglesModule.deg2rad;lib.rad2deg=anglesModule.rad2deg;lib.angleDelta=anglesModule.angleDelta;lib.angleDist=anglesModule.angleDist;lib.isFullCircle=anglesModule.isFullCircle;lib.isAngleInsideSector=anglesModule.isAngleInsideSector;lib.isPtInsideSector=anglesModule.isPtInsideSector;lib.pathArc=anglesModule.pathArc;lib.pathSector=anglesModule.pathSector;lib.pathAnnulus=anglesModule.pathAnnulus;var anchorUtils=_dereq_('./anchor_utils');lib.isLeftAnchor=anchorUtils.isLeftAnchor;lib.isCenterAnchor=anchorUtils.isCenterAnchor;lib.isRightAnchor=anchorUtils.isRightAnchor;lib.isTopAnchor=anchorUtils.isTopAnchor;lib.isMiddleAnchor=anchorUtils.isMiddleAnchor;lib.isBottomAnchor=anchorUtils.isBottomAnchor;var geom2dModule=_dereq_('./geometry2d');lib.segmentsIntersect=geom2dModule.segmentsIntersect;lib.segmentDistance=geom2dModule.segmentDistance;lib.getTextLocation=geom2dModule.getTextLocation;lib.clearLocationCache=geom2dModule.clearLocationCache;lib.getVisibleSegment=geom2dModule.getVisibleSegment;lib.findPointOnPath=geom2dModule.findPointOnPath;var extendModule=_dereq_('./extend');lib.extendFlat=extendModule.extendFlat;lib.extendDeep=extendModule.extendDeep;lib.extendDeepAll=extendModule.extendDeepAll;lib.extendDeepNoArrays=extendModule.extendDeepNoArrays;var loggersModule=_dereq_('./loggers');lib.log=loggersModule.log;lib.warn=loggersModule.warn;lib.error=loggersModule.error;var regexModule=_dereq_('./regex');lib.counterRegex=regexModule.counter;var throttleModule=_dereq_('./throttle');lib.throttle=throttleModule.throttle;lib.throttleDone=throttleModule.done;lib.clearThrottle=throttleModule.clear;var domModule=_dereq_('./dom');lib.getGraphDiv=domModule.getGraphDiv;lib.isPlotDiv=domModule.isPlotDiv;lib.removeElement=domModule.removeElement;lib.addStyleRule=domModule.addStyleRule;lib.addRelatedStyleRule=domModule.addRelatedStyleRule;lib.deleteRelatedStyleRule=domModule.deleteRelatedStyleRule;lib.clearResponsive=_dereq_('./clear_responsive');lib.makeTraceGroups=_dereq_('./make_trace_groups');lib._=_dereq_('./localize');lib.notifier=_dereq_('./notifier');lib.filterUnique=_dereq_('./filter_unique');lib.filterVisible=_dereq_('./filter_visible');lib.pushUnique=_dereq_('./push_unique');lib.cleanNumber=_dereq_('./clean_number');lib.ensureNumber=function ensureNumber(v){if(!isNumeric(v))return BADNUM;v=Number(v);if(v<-FP_SAFE||v>FP_SAFE)return BADNUM;return isNumeric(v)?Number(v):BADNUM;};/**\n * Is v a valid array index? Accepts numeric strings as well as numbers.\n *\n * @param {any} v: the value to test\n * @param {Optional[integer]} len: the array length we are indexing\n *\n * @return {bool}: v is a valid array index\n */lib.isIndex=function(v,len){if(len!==undefined&&v>=len)return false;return isNumeric(v)&&v>=0&&v%1===0;};lib.noop=_dereq_('./noop');lib.identity=_dereq_('./identity');/**\n * create an array of length 'cnt' filled with 'v' at all indices\n *\n * @param {any} v\n * @param {number} cnt\n * @return {array}\n */lib.repeat=function(v,cnt){var out=new Array(cnt);for(var i=0;iv1)return Math.max(v1,Math.min(v0,v));return Math.max(v0,Math.min(v1,v));};/**\n * do two bounding boxes from getBoundingClientRect,\n * ie {left,right,top,bottom,width,height}, overlap?\n * takes optional padding pixels\n */lib.bBoxIntersect=function(a,b,pad){pad=pad||0;return a.left<=b.right+pad&&b.left<=a.right+pad&&a.top<=b.bottom+pad&&b.top<=a.bottom+pad;};/*\n * simpleMap: alternative to Array.map that only\n * passes on the element and up to 2 extra args you\n * provide (but not the array index or the whole array)\n *\n * array: the array to map it to\n * func: the function to apply\n * x1, x2: optional extra args\n */lib.simpleMap=function(array,func,x1,x2){var len=array.length;var out=new Array(len);for(var i=0;i=Math.pow(2,bits)){if(_recursion>10){lib.warn('randstr failed uniqueness');return res;}return randstr(existing,bits,base,(_recursion||0)+1);}else return res;};lib.OptionControl=function(opt,optname){/*\n * An environment to contain all option setters and\n * getters that collectively modify opts.\n *\n * You can call up opts from any function in new object\n * as this.optname || this.opt\n *\n * See FitOpts for example of usage\n */if(!opt)opt={};if(!optname)optname='opt';var self={};self.optionList=[];self._newoption=function(optObj){optObj[optname]=opt;self[optObj.name]=optObj;self.optionList.push(optObj);};self['_'+optname]=opt;return self;};/**\n * lib.smooth: smooth arrayIn by convolving with\n * a hann window with given full width at half max\n * bounce the ends in, so the output has the same length as the input\n */lib.smooth=function(arrayIn,FWHM){FWHM=Math.round(FWHM)||0;// only makes sense for integers\nif(FWHM<2)return arrayIn;var alen=arrayIn.length;var alen2=2*alen;var wlen=2*FWHM-1;var w=new Array(wlen);var arrayOut=new Array(alen);var i;var j;var k;var v;// first make the window array\nfor(i=0;i=alen2)k-=alen2*Math.floor(k/alen2);// single bounce\nif(k<0)k=-1-k;else if(k>=alen)k=alen2-1-k;v+=arrayIn[k]*w[j];}arrayOut[i]=v;}return arrayOut;};/**\n * syncOrAsync: run a sequence of functions synchronously\n * as long as its returns are not promises (ie have no .then)\n * includes one argument arg to send to all functions...\n * this is mainly just to prevent us having to make wrapper functions\n * when the only purpose of the wrapper is to reference gd\n * and a final step to be executed at the end\n * TODO: if there's an error and everything is sync,\n * this doesn't happen yet because we want to make sure\n * that it gets reported\n */lib.syncOrAsync=function(sequence,arg,finalStep){var ret,fni;function continueAsync(){return lib.syncOrAsync(sequence,arg,finalStep);}while(sequence.length){fni=sequence.splice(0,1)[0];ret=fni(arg);if(ret&&ret.then){return ret.then(continueAsync).then(undefined,lib.promiseError);}}return finalStep&&finalStep(arg);};/**\n * Helper to strip trailing slash, from\n * http://stackoverflow.com/questions/6680825/return-string-without-trailing-slash\n */lib.stripTrailingSlash=function(str){if(str.substr(-1)==='/')return str.substr(0,str.length-1);return str;};lib.noneOrAll=function(containerIn,containerOut,attrList){/**\n * some attributes come together, so if you have one of them\n * in the input, you should copy the default values of the others\n * to the input as well.\n */if(!containerIn)return;var hasAny=false;var hasAll=true;var i;var val;for(i=0;i0?w:0;});};/** fills calcdata field (given by cdAttr) with traceAttr values\n * or function of traceAttr values (e.g. some fallback)\n *\n * N.B. Loops over all cd items.\n *\n * @param {array} traceAttr : trace attribute\n * @param {object} cd : calcdata trace\n * @param {string} cdAttr : calcdata key\n * @param {function} [fn] : optional function to apply to each array item\n */lib.fillArray=function(traceAttr,cd,cdAttr,fn){fn=fn||lib.identity;if(lib.isArrayOrTypedArray(traceAttr)){for(var i=0;i or 1 elements\n * because extend-like algorithms are hella slow\n * obj2 is assumed to already be clean of these things (including no arrays)\n */lib.minExtend=function(obj1,obj2){var objOut={};if(typeof obj2!=='object')obj2={};var arrayLen=3;var keys=Object.keys(obj1);var i,k,v;for(i=0;i { nested: { test: {path: 'value'}}}\n *\n * It also handles array notation, e.g.:\n *\n * lib.expandObjectPaths({'foo[1].bar': 'value'});\n * => { foo: [null, {bar: value}] }\n *\n * It handles merges the results when two properties are specified in parallel:\n *\n * lib.expandObjectPaths({'foo[1].bar': 10, 'foo[0].bar': 20});\n * => { foo: [{bar: 10}, {bar: 20}] }\n *\n * It does NOT, however, merge mulitple mutliply-nested arrays::\n *\n * lib.expandObjectPaths({'marker[1].range[1]': 5, 'marker[1].range[0]': 4})\n * => { marker: [null, {range: 4}] }\n */ // Store this to avoid recompiling regex on *every* prop since this may happen many\n// many times for animations. Could maybe be inside the function. Not sure about\n// scoping vs. recompilation tradeoff, but at least it's not just inlining it into\n// the inner loop.\nvar dottedPropertyRegex=/^([^\\[\\.]+)\\.(.+)?/;var indexedPropertyRegex=/^([^\\.]+)\\[([0-9]+)\\](\\.)?(.+)?/;lib.expandObjectPaths=function(data){var match,key,prop,datum,idx,dest,trailingPath;if(typeof data==='object'&&!Array.isArray(data)){for(key in data){if(data.hasOwnProperty(key)){if(match=key.match(dottedPropertyRegex)){datum=data[key];prop=match[1];delete data[key];data[prop]=lib.extendDeepNoArrays(data[prop]||{},lib.objectFromPath(key,lib.expandObjectPaths(datum))[prop]);}else if(match=key.match(indexedPropertyRegex)){datum=data[key];prop=match[1];idx=parseInt(match[2]);delete data[key];data[prop]=data[prop]||[];if(match[3]==='.'){// This is the case where theere are subsequent properties into which\n// we must recurse, e.g. transforms[0].value\ntrailingPath=match[4];dest=data[prop][idx]=data[prop][idx]||{};// NB: Extend deep no arrays prevents this from working on multiple\n// nested properties in the same object, e.g.\n//\n// {\n// foo[0].bar[1].range\n// foo[0].bar[0].range\n// }\n//\n// In this case, the extendDeepNoArrays will overwrite one array with\n// the other, so that both properties *will not* be present in the\n// result. Fixing this would require a more intelligent tracking\n// of changes and merging than extendDeepNoArrays currently accomplishes.\nlib.extendDeepNoArrays(dest,lib.objectFromPath(trailingPath,lib.expandObjectPaths(datum)));}else{// This is the case where this property is the end of the line,\n// e.g. xaxis.range[0]\ndata[prop][idx]=lib.expandObjectPaths(datum);}}else{data[key]=lib.expandObjectPaths(data[key]);}}}}return data;};/**\n * Converts value to string separated by the provided separators.\n *\n * @example\n * lib.numSeparate(2016, '.,');\n * // returns '2016'\n *\n * @example\n * lib.numSeparate(3000, '.,', true);\n * // returns '3,000'\n *\n * @example\n * lib.numSeparate(1234.56, '|,')\n * // returns '1,234|56'\n *\n * @param {string|number} value the value to be converted\n * @param {string} separators string of decimal, then thousands separators\n * @param {boolean} separatethousands boolean, 4-digit integers are separated if true\n *\n * @return {string} the value that has been separated\n */lib.numSeparate=function(value,separators,separatethousands){if(!separatethousands)separatethousands=false;if(typeof separators!=='string'||separators.length===0){throw new Error('Separator string required for formatting!');}if(typeof value==='number'){value=String(value);}var thousandsRe=/(\\d+)(\\d{3})/;var decimalSep=separators.charAt(0);var thouSep=separators.charAt(1);var x=value.split('.');var x1=x[0];var x2=x.length>1?decimalSep+x[1]:'';// Years are ignored for thousands separators\nif(thouSep&&(x.length>1||x1.length>4||separatethousands)){while(thousandsRe.test(x1)){x1=x1.replace(thousandsRe,'$1'+thouSep+'$2');}}return x1+x2;};lib.TEMPLATE_STRING_REGEX=/%{([^\\s%{}:]*)([:|\\|][^}]*)?}/g;var SIMPLE_PROPERTY_REGEX=/^\\w*$/;/**\n * Substitute values from an object into a string\n *\n * Examples:\n * Lib.templateString('name: %{trace}', {trace: 'asdf'}) --> 'name: asdf'\n * Lib.templateString('name: %{trace[0].name}', {trace: [{name: 'asdf'}]}) --> 'name: asdf'\n *\n * @param {string} input string containing %{...} template strings\n * @param {obj} data object containing substitution values\n *\n * @return {string} templated string\n */lib.templateString=function(string,obj){// Not all that useful, but cache nestedProperty instantiation\n// just in case it speeds things up *slightly*:\nvar getterCache={};return string.replace(lib.TEMPLATE_STRING_REGEX,function(dummy,key){var v;if(SIMPLE_PROPERTY_REGEX.test(key)){v=obj[key];}else{getterCache[key]=getterCache[key]||lib.nestedProperty(obj,key).get;v=getterCache[key]();}return lib.isValidTextValue(v)?v:'';});};var hovertemplateWarnings={max:10,count:0,name:'hovertemplate'};lib.hovertemplateString=function(){return templateFormatString.apply(hovertemplateWarnings,arguments);};var texttemplateWarnings={max:10,count:0,name:'texttemplate'};lib.texttemplateString=function(){return templateFormatString.apply(texttemplateWarnings,arguments);};var TEMPLATE_STRING_FORMAT_SEPARATOR=/^[:|\\|]/;/**\n * Substitute values from an object into a string and optionally formats them using d3-format,\n * or fallback to associated labels.\n *\n * Examples:\n * Lib.hovertemplateString('name: %{trace}', {trace: 'asdf'}) --> 'name: asdf'\n * Lib.hovertemplateString('name: %{trace[0].name}', {trace: [{name: 'asdf'}]}) --> 'name: asdf'\n * Lib.hovertemplateString('price: %{y:$.2f}', {y: 1}) --> 'price: $1.00'\n *\n * @param {string} input string containing %{...:...} template strings\n * @param {obj} data object containing fallback text when no formatting is specified, ex.: {yLabel: 'formattedYValue'}\n * @param {obj} d3 locale\n * @param {obj} data objects containing substitution values\n *\n * @return {string} templated string\n */function templateFormatString(string,labels,d3locale){var opts=this;var args=arguments;if(!labels)labels={};// Not all that useful, but cache nestedProperty instantiation\n// just in case it speeds things up *slightly*:\nvar getterCache={};return string.replace(lib.TEMPLATE_STRING_REGEX,function(match,key,format){var obj,value,i;for(i=3;i=char0&&charA<=char9;var isNumB=charB>=char0&&charB<=char9;if(isNumA)numA=10*numA+charA-char0;if(isNumB)numB=10*numB+charB-char0;if(!isNumA||!isNumB){if(numA!==numB)return numA-numB;if(charA!==charB)return charA-charB;}}return numB-numA;};// repeatable pseudorandom generator\nvar randSeed=2000000000;lib.seedPseudoRandom=function(){randSeed=2000000000;};lib.pseudoRandom=function(){var lastVal=randSeed;randSeed=(69069*randSeed+1)%4294967296;// don't let consecutive vals be too close together\n// gets away from really trying to be random, in favor of better local uniformity\nif(Math.abs(randSeed-lastVal)<429496729)return lib.pseudoRandom();return randSeed/4294967296;};/** Fill hover 'pointData' container with 'correct' hover text value\n *\n * - If trace hoverinfo contains a 'text' flag and hovertext is not set,\n * the text elements will be seen in the hover labels.\n *\n * - If trace hoverinfo contains a 'text' flag and hovertext is set,\n * hovertext takes precedence over text\n * i.e. the hoverinfo elements will be seen in the hover labels\n *\n * @param {object} calcPt\n * @param {object} trace\n * @param {object || array} contOut (mutated here)\n */lib.fillText=function(calcPt,trace,contOut){var fill=Array.isArray(contOut)?function(v){contOut.push(v);}:function(v){contOut.text=v;};var htx=lib.extractOption(calcPt,trace,'htx','hovertext');if(lib.isValidTextValue(htx))return fill(htx);var tx=lib.extractOption(calcPt,trace,'tx','text');if(lib.isValidTextValue(tx))return fill(tx);};// accept all truthy values and 0 (which gets cast to '0' in the hover labels)\nlib.isValidTextValue=function(v){return v||v===0;};/**\n * @param {number} ratio\n * @param {number} n (number of decimal places)\n */lib.formatPercent=function(ratio,n){n=n||0;var str=(Math.round(100*ratio*Math.pow(10,n))*Math.pow(0.1,n)).toFixed(n)+'%';for(var i=0;i1)scale=1;return'translate('+(targetX-scale*(textX+anchorX))+','+(targetY-scale*(textY+anchorY))+')'+(scale<1?'scale('+scale+')':'')+(rotate?'rotate('+rotate+(noCenter?'':' '+textX+' '+textY)+')':'');};lib.ensureUniformFontSize=function(gd,baseFont){var out=lib.extendFlat({},baseFont);out.size=Math.max(baseFont.size,gd._fullLayout.uniformtext.minsize||0);return out;};},{\"../constants/numerical\":711,\"./anchor_utils\":716,\"./angles\":717,\"./array\":718,\"./clean_number\":719,\"./clear_responsive\":721,\"./coerce\":722,\"./dates\":723,\"./dom\":724,\"./extend\":726,\"./filter_unique\":727,\"./filter_visible\":728,\"./geometry2d\":731,\"./identity\":734,\"./is_plain_object\":736,\"./keyed_container\":737,\"./localize\":738,\"./loggers\":739,\"./make_trace_groups\":740,\"./matrix\":741,\"./mod\":742,\"./nested_property\":743,\"./noop\":744,\"./notifier\":745,\"./push_unique\":749,\"./regex\":751,\"./relative_attr\":752,\"./relink_private\":753,\"./search\":754,\"./stats\":757,\"./throttle\":760,\"./to_log_range\":761,\"d3\":165,\"fast-isnumeric\":237}],736:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';// more info: http://stackoverflow.com/questions/18531624/isplainobject-thing\nmodule.exports=function isPlainObject(obj){// We need to be a little less strict in the `imagetest` container because\n// of how async image requests are handled.\n//\n// N.B. isPlainObject(new Constructor()) will return true in `imagetest`\nif(window&&window.process&&window.process.versions){return Object.prototype.toString.call(obj)==='[object Object]';}return Object.prototype.toString.call(obj)==='[object Object]'&&Object.getPrototypeOf(obj)===Object.prototype;};},{}],737:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var nestedProperty=_dereq_('./nested_property');var SIMPLE_PROPERTY_REGEX=/^\\w*$/;// bitmask for deciding what's updated. Sometimes the name needs to be updated,\n// sometimes the value needs to be updated, and sometimes both do. This is just\n// a simple way to track what's updated such that it's a simple OR operation to\n// assimilate new updates.\n//\n// The only exception is the UNSET bit that tracks when we need to explicitly\n// unset and remove the property. This concrn arises because of the special\n// way in which nestedProperty handles null/undefined. When you specify `null`,\n// it prunes any unused items in the tree. I ran into some issues with it getting\n// null vs undefined confused, so UNSET is just a bit that forces the property\n// update to send `null`, removing the property explicitly rather than setting\n// it to undefined.\nvar NONE=0;var NAME=1;var VALUE=2;var BOTH=3;var UNSET=4;module.exports=function keyedContainer(baseObj,path,keyName,valueName){keyName=keyName||'name';valueName=valueName||'value';var i,arr,baseProp;var changeTypes={};if(path&&path.length){baseProp=nestedProperty(baseObj,path);arr=baseProp.get();}else{arr=baseObj;}path=path||'';// Construct an index:\nvar indexLookup={};if(arr){for(i=0;i2){// This object contains more than just the key/value, so unset\n// the value without modifying the entry otherwise:\nchangeTypes[idx]=changeTypes[idx]|VALUE;return obj.set(name,null);}if(isSimpleValueProp){for(i=idx;i1){var messages=['LOG:'];for(i=0;i1){var lines=[];for(i=0;i'),'long');}};loggers.warn=function(){var i;if(dfltConfig.logging>0){var messages=['WARN:'];for(i=0;i0){var lines=[];for(i=0;i'),'stick');}};loggers.error=function(){var i;if(dfltConfig.logging>0){var messages=['ERROR:'];for(i=0;i0){var lines=[];for(i=0;i'),'stick');}};/*\n * Robust apply, for IE9 where console.log doesn't support\n * apply like other functions do\n */function apply(f,args){if(f&&f.apply){try{// `this` should always be console, since here we're always\n// applying a method of the console object.\nf.apply(console,args);return;}catch(e){/* in case apply failed, fall back on the code below */}}// no apply - just try calling the function on each arg independently\nfor(var i=0;id/2?v-Math.round(v/d)*d:v;}module.exports={mod:mod,modHalf:modHalf};},{}],743:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var isNumeric=_dereq_('fast-isnumeric');var isArrayOrTypedArray=_dereq_('./array').isArrayOrTypedArray;/**\n * convert a string s (such as 'xaxis.range[0]')\n * representing a property of nested object into set and get methods\n * also return the string and object so we don't have to keep track of them\n * allows [-1] for an array index, to set a property inside all elements\n * of an array\n * eg if obj = {arr: [{a: 1}, {a: 2}]}\n * you can do p = nestedProperty(obj, 'arr[-1].a')\n * but you cannot set the array itself this way, to do that\n * just set the whole array.\n * eg if obj = {arr: [1, 2, 3]}\n * you can't do nestedProperty(obj, 'arr[-1]').set(5)\n * but you can do nestedProperty(obj, 'arr').set([5, 5, 5])\n */module.exports=function nestedProperty(container,propStr){if(isNumeric(propStr))propStr=String(propStr);else if(typeof propStr!=='string'||propStr.substr(propStr.length-4)==='[-1]'){throw'bad property string';}var j=0;var propParts=propStr.split('.');var indexed;var indices;var i;// check for parts of the nesting hierarchy that are numbers (ie array elements)\nwhile(j/g);for(var i=0;ixmax||y===BADNUM||yymax){// pt is outside the bounding box of polygon\nreturn false;}if(omitFirstEdge&&rectFirstEdgeTest(pt))return false;return true;}function contains(pt,omitFirstEdge){var x=pt[0];var y=pt[1];if(x===BADNUM||xxmax||y===BADNUM||yymax){// pt is outside the bounding box of polygon\nreturn false;}var imax=pts.length;var x1=pts[0][0];var y1=pts[0][1];var crossings=0;var i;var x0;var y0;var xmini;var ycross;for(i=1;iMath.max(x0,x1)||y>Math.max(y0,y1)){// outside the bounding box of this segment, it's only a crossing\n// if it's below the box.\ncontinue;}else if(ysegmentSquared||Math.abs(dot(part,unitPerp))>tolerance)return true;}return false;};/**\n * Make a filtering polygon, to minimize the number of segments\n *\n * @param pts Array of [x, y] pairs (must start with at least 1 pair)\n * @param tolerance the maximum deviation from straight allowed for\n * removing points to simplify the polygon\n *\n * @returns Object {addPt, raw, filtered}\n * addPt is a function(pt: [x, y] pair) to add a raw point and\n * continue filtering\n * raw is all the input points\n * filtered is the resulting filtered Array of [x, y] pairs\n */polygon.filter=function filter(pts,tolerance){var ptsFiltered=[pts[0]];var doneRawIndex=0;var doneFilteredIndex=0;function addPt(pt){pts.push(pt);var prevFilterLen=ptsFiltered.length;var iLast=doneRawIndex;ptsFiltered.splice(doneFilteredIndex+1);for(var i=iLast+1;i1){var lastPt=pts.pop();addPt(lastPt);}return{addPt:addPt,raw:pts,filtered:ptsFiltered};};},{\"../constants/numerical\":711,\"./matrix\":741}],748:[function(_dereq_,module,exports){(function(global){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var showNoWebGlMsg=_dereq_('./show_no_webgl_msg');// Note that this module should be ONLY required into\n// files corresponding to regl trace modules\n// so that bundles with non-regl only don't include\n// regl and all its bytes.\nvar createRegl=_dereq_('regl');/**\n * Idempotent version of createRegl. Create regl instances\n * in the correct canvases with the correct attributes and\n * options\n *\n * @param {DOM node or object} gd : graph div object\n * @param {array} extensions : list of extension to pass to createRegl\n *\n * @return {boolean} true if all createRegl calls succeeded, false otherwise\n */module.exports=function prepareRegl(gd,extensions){var fullLayout=gd._fullLayout;var success=true;fullLayout._glcanvas.each(function(d){if(d.regl)return;// only parcoords needs pick layer\nif(d.pick&&!fullLayout._has('parcoords'))return;try{d.regl=createRegl({canvas:this,attributes:{antialias:!d.pick,preserveDrawingBuffer:true},pixelRatio:gd._context.plotGlPixelRatio||global.devicePixelRatio,extensions:extensions||[]});}catch(e){success=false;}if(!d.regl)success=false;if(success){this.addEventListener('webglcontextlost',function(event){if(gd&&gd.emit){gd.emit('plotly_webglcontextlost',{event:event,layer:d.key});}},false);}});if(!success){showNoWebGlMsg({container:fullLayout._glcontainer.node()});}return success;};}).call(this,typeof global!==\"undefined\"?global:typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{});},{\"./show_no_webgl_msg\":756,\"regl\":499}],749:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';/**\n * Push array with unique items\n *\n * Ignores falsy items, except 0 so we can use it to construct arrays of indices.\n *\n * @param {array} array\n * array to be filled\n * @param {any} item\n * item to be or not to be inserted\n * @return {array}\n * ref to array (now possibly containing one more item)\n *\n */module.exports=function pushUnique(array,item){if(item instanceof RegExp){var itemStr=item.toString();for(var i=0;idfltConfig.queueLength){gd.undoQueue.queue.shift();gd.undoQueue.index--;}};/**\n * Begin a sequence of undoQueue changes\n *\n * @param gd\n */queue.startSequence=function(gd){gd.undoQueue=gd.undoQueue||{index:0,queue:[],sequence:false};gd.undoQueue.sequence=true;gd.undoQueue.beginSequence=true;};/**\n * Stop a sequence of undoQueue changes\n *\n * Call this *after* you're sure your undo chain has ended\n *\n * @param gd\n */queue.stopSequence=function(gd){gd.undoQueue=gd.undoQueue||{index:0,queue:[],sequence:false};gd.undoQueue.sequence=false;gd.undoQueue.beginSequence=false;};/**\n * Move one step back in the undo queue, and undo the object there.\n *\n * @param gd\n */queue.undo=function undo(gd){var queueObj,i;if(gd.framework&&gd.framework.isPolar){gd.framework.undo();return;}if(gd.undoQueue===undefined||isNaN(gd.undoQueue.index)||gd.undoQueue.index<=0){return;}// index is pointing to next *forward* queueObj, point to the one we're undoing\ngd.undoQueue.index--;// get the queueObj for instructions on how to undo\nqueueObj=gd.undoQueue.queue[gd.undoQueue.index];// this sequence keeps things from adding to the queue during undo/redo\ngd.undoQueue.inSequence=true;for(i=0;i=gd.undoQueue.queue.length){return;}// get the queueObj for instructions on how to undo\nqueueObj=gd.undoQueue.queue[gd.undoQueue.index];// this sequence keeps things from adding to the queue during undo/redo\ngd.undoQueue.inSequence=true;for(i=0;i] or . - to ascend\n// the attribute tree. the remaining attrString is in match[1]\nvar ASCEND=/^(.*)(\\.[^\\.\\[\\]]+|\\[\\d\\])$/;// SIMPLEATTR: is this an un-nested attribute? (no dots or brackets)\nvar SIMPLEATTR=/^[^\\.\\[\\]]+$/;/*\n * calculate a relative attribute string, similar to a relative path\n *\n * @param {string} baseAttr:\n * an attribute string, such as 'annotations[3].x'. The \"current location\"\n * is the attribute string minus the last component ('annotations[3]')\n * @param {string} relativeAttr:\n * a route to the desired attribute string, using '^' to ascend\n *\n * @return {string} attrString:\n * for example:\n * relativeAttr('annotations[3].x', 'y') = 'annotations[3].y'\n * relativeAttr('annotations[3].x', '^[2].z') = 'annotations[2].z'\n * relativeAttr('annotations[3].x', '^^margin') = 'margin'\n * relativeAttr('annotations[3].x', '^^margin.r') = 'margin.r'\n */module.exports=function(baseAttr,relativeAttr){while(relativeAttr){var match=baseAttr.match(ASCEND);if(match)baseAttr=match[1];else if(baseAttr.match(SIMPLEATTR))baseAttr='';else throw new Error('bad relativeAttr call:'+[baseAttr,relativeAttr]);if(relativeAttr.charAt(0)==='^')relativeAttr=relativeAttr.slice(1);else break;}if(baseAttr&&relativeAttr.charAt(0)!=='['){return baseAttr+'.'+relativeAttr;}return baseAttr+relativeAttr;};},{}],753:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var isArrayOrTypedArray=_dereq_('./array').isArrayOrTypedArray;var isPlainObject=_dereq_('./is_plain_object');/**\n * Relink private _keys and keys with a function value from one container\n * to the new container.\n * Relink means copying if object is pass-by-value and adding a reference\n * if object is pass-by-ref.\n * This prevents deepCopying massive structures like a webgl context.\n */module.exports=function relinkPrivateKeys(toContainer,fromContainer){for(var k in fromContainer){var fromVal=fromContainer[k];var toVal=toContainer[k];if(toVal===fromVal){continue;}if(k.charAt(0)==='_'||typeof fromVal==='function'){// if it already exists at this point, it's something\n// that we recreate each time around, so ignore it\nif(k in toContainer)continue;toContainer[k]=fromVal;}else if(isArrayOrTypedArray(fromVal)&&isArrayOrTypedArray(toVal)&&isPlainObject(fromVal[0])){// filter out data_array items that can contain user objects\n// most of the time the toVal === fromVal check will catch these early\n// but if the user makes new ones we also don't want to recurse in.\nif(k==='customdata'||k==='ids')continue;// recurse into arrays containers\nvar minLen=Math.min(fromVal.length,toVal.length);for(var j=0;j1?(bins[n2-1]-bins[0])/(n2-1):1;var n,test;if(binSize>=0){test=linelow?lessThan:lessOrEqual;}else{test=linelow?greaterOrEqual:greaterThan;}val+=binSize*roundingError*(linelow?-1:1)*(binSize>=0?1:-1);// c is just to avoid infinite loops if there's an error\nwhile(n190)loggers.log('Long binary search...');return n1-1;}};function lessThan(a,b){return ab;}function greaterOrEqual(a,b){return a>=b;}exports.sorterAsc=function(a,b){return a-b;};exports.sorterDes=function(a,b){return b-a;};/**\n * find distinct values in an array, lumping together ones that appear to\n * just be off by a rounding error\n * return the distinct values and the minimum difference between any two\n */exports.distinctVals=function(valsIn){var vals=valsIn.slice();// otherwise we sort the original array...\nvals.sort(exports.sorterAsc);var l=vals.length-1;var minDiff=vals[l]-vals[0]||1;var errDiff=minDiff/(l||1)/10000;var v2=[vals[0]];for(var i=0;ivals[i]+errDiff){minDiff=Math.min(minDiff,vals[i+1]-vals[i]);v2.push(vals[i+1]);}}return{vals:v2,minDiff:minDiff};};/**\n * return the smallest element from (sorted) array arrayIn that's bigger than val,\n * or (reverse) the largest element smaller than val\n * used to find the best tick given the minimum (non-rounded) tick\n * particularly useful for date/time where things are not powers of 10\n * binary search is probably overkill here...\n */exports.roundUp=function(val,arrayIn,reverse){var low=0;var high=arrayIn.length-1;var mid;var c=0;var dlow=reverse?0:1;var dhigh=reverse?1:0;var rounded=reverse?Math.ceil:Math.floor;// c is just to avoid infinite loops if there's an error\nwhile(low0)notReversed=1;if(notOrdered&¬Reversed)return array.sort(sortFn);}return notReversed?array:array.reverse();};/**\n * find index in array 'arr' that minimizes 'fn'\n *\n * @param {array} arr : array where to search\n * @param {fn (optional)} fn : function to minimize,\n * if not given, fn is the identity function\n * @return {integer}\n */exports.findIndexOfMin=function(arr,fn){fn=fn||identity;var min=Infinity;var ind;for(var i=0;ia.length)len=a.length;if(!isNumeric(v))v=false;if(isArrayOrTypedArray(a[0])){b=new Array(len);for(i=0;iarr.length-1)return arr[arr.length-1];var frac=n%1;return frac*arr[Math.ceil(n)]+(1-frac)*arr[Math.floor(n)];};},{\"./array\":718,\"fast-isnumeric\":237}],758:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var rgba=_dereq_('color-normalize');function str2RgbaArray(color){if(!color)return[0,0,0,1];return rgba(color);}module.exports=str2RgbaArray;},{\"color-normalize\":122}],759:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';/* global MathJax:false */var d3=_dereq_('d3');var Lib=_dereq_('../lib');var xmlnsNamespaces=_dereq_('../constants/xmlns_namespaces');var LINE_SPACING=_dereq_('../constants/alignment').LINE_SPACING;// text converter\nfunction getSize(_selection,_dimension){return _selection.node().getBoundingClientRect()[_dimension];}var FIND_TEX=/([^$]*)([$]+[^$]*[$]+)([^$]*)/;exports.convertToTspans=function(_context,gd,_callback){var str=_context.text();// Until we get tex integrated more fully (so it can be used along with non-tex)\n// allow some elements to prohibit it by attaching 'data-notex' to the original\nvar tex=!_context.attr('data-notex')&&typeof MathJax!=='undefined'&&str.match(FIND_TEX);var parent=d3.select(_context.node().parentNode);if(parent.empty())return;var svgClass=_context.attr('class')?_context.attr('class').split(' ')[0]:'text';svgClass+='-math';parent.selectAll('svg.'+svgClass).remove();parent.selectAll('g.'+svgClass+'-group').remove();_context.style('display',null).attr({// some callers use data-unformatted *from the element* in 'cancel'\n// so we need it here even if we're going to turn it into math\n// these two (plus style and text-anchor attributes) form the key we're\n// going to use for Drawing.bBox\n'data-unformatted':str,'data-math':'N'});function showText(){if(!parent.empty()){svgClass=_context.attr('class')+'-math';parent.select('svg.'+svgClass).remove();}_context.text('').style('white-space','pre');var hasLink=buildSVGText(_context.node(),str);if(hasLink){// at least in Chrome, pointer-events does not seem\n// to be honored in children of elements\n// so if we have an anchor, we have to make the\n// whole element respond\n_context.style('pointer-events','all');}exports.positionText(_context);if(_callback)_callback.call(_context);}if(tex){(gd&&gd._promises||[]).push(new Promise(function(resolve){_context.style('display','none');var fontSize=parseInt(_context.node().style.fontSize,10);var config={fontSize:fontSize};texToSVG(tex[2],config,function(_svgEl,_glyphDefs,_svgBBox){parent.selectAll('svg.'+svgClass).remove();parent.selectAll('g.'+svgClass+'-group').remove();var newSvg=_svgEl&&_svgEl.select('svg');if(!newSvg||!newSvg.node()){showText();resolve();return;}var mathjaxGroup=parent.append('g').classed(svgClass+'-group',true).attr({'pointer-events':'none','data-unformatted':str,'data-math':'Y'});mathjaxGroup.node().appendChild(newSvg.node());// stitch the glyph defs\nif(_glyphDefs&&_glyphDefs.node()){newSvg.node().insertBefore(_glyphDefs.node().cloneNode(true),newSvg.node().firstChild);}newSvg.attr({'class':svgClass,height:_svgBBox.height,preserveAspectRatio:'xMinYMin meet'}).style({overflow:'visible','pointer-events':'none'});var fill=_context.node().style.fill||'black';var g=newSvg.select('g');g.attr({fill:fill,stroke:fill});var newSvgW=getSize(g,'width');var newSvgH=getSize(g,'height');var newX=+_context.attr('x')-newSvgW*{start:0,middle:0.5,end:1}[_context.attr('text-anchor')||'start'];// font baseline is about 1/4 fontSize below centerline\nvar textHeight=fontSize||getSize(_context,'height');var dy=-textHeight/4;if(svgClass[0]==='y'){mathjaxGroup.attr({transform:'rotate('+[-90,+_context.attr('x'),+_context.attr('y')]+') translate('+[-newSvgW/2,dy-newSvgH/2]+')'});newSvg.attr({x:+_context.attr('x'),y:+_context.attr('y')});}else if(svgClass[0]==='l'){newSvg.attr({x:_context.attr('x'),y:dy-newSvgH/2});}else if(svgClass[0]==='a'&&svgClass.indexOf('atitle')!==0){newSvg.attr({x:0,y:dy});}else{newSvg.attr({x:newX,y:+_context.attr('y')+dy-newSvgH/2});}if(_callback)_callback.call(_context,mathjaxGroup);resolve(mathjaxGroup);});}));}else showText();return _context;};// MathJax\nvar LT_MATCH=/(<|<|<)/g;var GT_MATCH=/(>|>|>)/g;function cleanEscapesForTex(s){return s.replace(LT_MATCH,'\\\\lt ').replace(GT_MATCH,'\\\\gt ');}function texToSVG(_texString,_config,_callback){var originalRenderer,originalConfig,originalProcessSectionDelay,tmpDiv;MathJax.Hub.Queue(function(){originalConfig=Lib.extendDeepAll({},MathJax.Hub.config);originalProcessSectionDelay=MathJax.Hub.processSectionDelay;if(MathJax.Hub.processSectionDelay!==undefined){// MathJax 2.5+\nMathJax.Hub.processSectionDelay=0;}return MathJax.Hub.Config({messageStyle:'none',tex2jax:{inlineMath:[['$','$'],['\\\\(','\\\\)']]},displayAlign:'left'});},function(){// Get original renderer\noriginalRenderer=MathJax.Hub.config.menuSettings.renderer;if(originalRenderer!=='SVG'){return MathJax.Hub.setRenderer('SVG');}},function(){var randomID='math-output-'+Lib.randstr({},64);tmpDiv=d3.select('body').append('div').attr({id:randomID}).style({visibility:'hidden',position:'absolute'}).style({'font-size':_config.fontSize+'px'}).text(cleanEscapesForTex(_texString));return MathJax.Hub.Typeset(tmpDiv.node());},function(){var glyphDefs=d3.select('body').select('#MathJax_SVG_glyphs');if(tmpDiv.select('.MathJax_SVG').empty()||!tmpDiv.select('svg').node()){Lib.log('There was an error in the tex syntax.',_texString);_callback();}else{var svgBBox=tmpDiv.select('svg').node().getBoundingClientRect();_callback(tmpDiv.select('.MathJax_SVG'),glyphDefs,svgBBox);}tmpDiv.remove();if(originalRenderer!=='SVG'){return MathJax.Hub.setRenderer(originalRenderer);}},function(){if(originalProcessSectionDelay!==undefined){MathJax.Hub.processSectionDelay=originalProcessSectionDelay;}return MathJax.Hub.Config(originalConfig);});}var TAG_STYLES={// would like to use baseline-shift for sub/sup but FF doesn't support it\n// so we need to use dy along with the uber hacky shift-back-to\n// baseline below\nsup:'font-size:70%',sub:'font-size:70%',b:'font-weight:bold',i:'font-style:italic',a:'cursor:pointer',span:'',em:'font-style:italic;font-weight:bold'};// baseline shifts for sub and sup\nvar SHIFT_DY={sub:'0.3em',sup:'-0.6em'};// reset baseline by adding a tspan (empty except for a zero-width space)\n// with dy of -70% * SHIFT_DY (because font-size=70%)\nvar RESET_DY={sub:'-0.21em',sup:'0.42em'};var ZERO_WIDTH_SPACE='\\u200b';/*\n * Whitelist of protocols in user-supplied urls. Mostly we want to avoid javascript\n * and related attack vectors. The empty items are there for IE, that in various\n * versions treats relative paths as having different flavors of no protocol, while\n * other browsers have these explicitly inherit the protocol of the page they're in.\n */var PROTOCOLS=['http:','https:','mailto:','',undefined,':'];var NEWLINES=exports.NEWLINES=/(\\r\\n?|\\n)/g;var SPLIT_TAGS=/(<[^<>]*>)/;var ONE_TAG=/<(\\/?)([^ >]*)(\\s+(.*))?>/i;var BR_TAG=/ /i;exports.BR_TAG_ALL=/ /gi;/*\n * style and href: pull them out of either single or double quotes. Also\n * - target: (_blank|_self|_parent|_top|framename)\n * note that you can't use target to get a popup but if you use popup,\n * a `framename` will be passed along as the name of the popup window.\n * per the spec, cannot contain whitespace.\n * for backward compatibility we default to '_blank'\n * - popup: a custom one for us to enable popup (new window) links. String\n * for window.open -> strWindowFeatures, like 'menubar=yes,width=500,height=550'\n * note that at least in Chrome, you need to give at least one property\n * in this string or the page will open in a new tab anyway. We follow this\n * convention and will not make a popup if this string is empty.\n * per the spec, cannot contain whitespace.\n *\n * Because we hack in other attributes with style (sub & sup), drop any trailing\n * semicolon in user-supplied styles so we can consistently append the tag-dependent style\n *\n * These are for tag attributes; Chrome anyway will convert entities in\n * attribute values, but not in attribute names\n * you can test this by for example:\n * > p = document.createElement('p')\n * > p.innerHTML = 'Hi '\n * > p.innerHTML\n * <- 'Hi '\n */var STYLEMATCH=/(^|[\\s\"'])style\\s*=\\s*(\"([^\"]*);?\"|'([^']*);?')/i;var HREFMATCH=/(^|[\\s\"'])href\\s*=\\s*(\"([^\"]*)\"|'([^']*)')/i;var TARGETMATCH=/(^|[\\s\"'])target\\s*=\\s*(\"([^\"\\s]*)\"|'([^'\\s]*)')/i;var POPUPMATCH=/(^|[\\s\"'])popup\\s*=\\s*(\"([\\w=,]*)\"|'([\\w=,]*)')/i;// dedicated matcher for these quoted regexes, that can return their results\n// in two different places\nfunction getQuotedMatch(_str,re){if(!_str)return null;var match=_str.match(re);var result=match&&(match[3]||match[4]);return result&&convertEntities(result);}var COLORMATCH=/(^|;)\\s*color:/;/**\n * Strip string of tags\n *\n * @param {string} _str : input string\n * @param {object} opts :\n * - len {number} max length of output string\n * - allowedTags {array} list of pseudo-html tags to NOT strip\n * @return {string}\n */exports.plainText=function(_str,opts){opts=opts||{};var len=opts.len!==undefined&&opts.len!==-1?opts.len:Infinity;var allowedTags=opts.allowedTags!==undefined?opts.allowedTags:['br'];var ellipsis='...';var eLen=ellipsis.length;var oldParts=_str.split(SPLIT_TAGS);var newParts=[];var prevTag='';var l=0;for(var i=0;ieLen){newParts.push(p.substr(0,pLen2-eLen)+ellipsis);}else{newParts.push(p.substr(0,pLen2));}break;}prevTag='';}}return newParts.join('');};/*\n * N.B. HTML entities are listed without the leading '&' and trailing ';'\n * https://www.freeformatter.com/html-entities.html\n *\n * FWIW if we wanted to support the full set, it has 2261 entries:\n * https://www.w3.org/TR/html5/entities.json\n * though I notice that some of these are duplicates and/or are missing \";\"\n * eg: \"&\", \"&\", \"&\", and \"&\" all map to \"&\"\n * We no longer need to include numeric entities here, these are now handled\n * by String.fromCodePoint/fromCharCode\n *\n * Anyway the only ones that are really important to allow are the HTML special\n * chars <, >, and &, because these ones can trigger special processing if not\n * replaced by the corresponding entity.\n */var entityToUnicode={mu:'μ',amp:'&',lt:'<',gt:'>',nbsp:' ',times:'×',plusmn:'±',deg:'°'};// NOTE: in general entities can contain uppercase too (so [a-zA-Z]) but all the\n// ones we support use only lowercase. If we ever change that, update the regex.\nvar ENTITY_MATCH=/&(#\\d+|#x[\\da-fA-F]+|[a-z]+);/g;function convertEntities(_str){return _str.replace(ENTITY_MATCH,function(fullMatch,innerMatch){var outChar;if(innerMatch.charAt(0)==='#'){// cannot use String.fromCodePoint in IE\noutChar=fromCodePoint(innerMatch.charAt(1)==='x'?parseInt(innerMatch.substr(2),16):parseInt(innerMatch.substr(1),10));}else outChar=entityToUnicode[innerMatch];// as in regular HTML, if we didn't decode the entity just\n// leave the raw text in place.\nreturn outChar||fullMatch;});}exports.convertEntities=convertEntities;function fromCodePoint(code){// Don't allow overflow. In Chrome this turns into � but I feel like it's\n// more useful to just not convert it at all.\nif(code>0x10FFFF)return;var stringFromCodePoint=String.fromCodePoint;if(stringFromCodePoint)return stringFromCodePoint(code);// IE doesn't have String.fromCodePoint\n// see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint\nvar stringFromCharCode=String.fromCharCode;if(code<=0xFFFF)return stringFromCharCode(code);return stringFromCharCode((code>>10)+0xD7C0,code%0x400+0xDC00);}/*\n * buildSVGText: convert our pseudo-html into SVG tspan elements, and attach these\n * to containerNode\n *\n * @param {svg text element} containerNode: the node to insert this text into\n * @param {string} str: the pseudo-html string to convert to svg\n *\n * @returns {bool}: does the result contain any links? We need to handle the text element\n * somewhat differently if it does, so just keep track of this when it happens.\n */function buildSVGText(containerNode,str){/*\n * Normalize behavior between IE and others wrt newlines and whitespace:pre\n * this combination makes IE barf https://github.com/plotly/plotly.js/issues/746\n * Chrome and FF display \\n, \\r, or \\r\\n as a space in this mode.\n * I feel like at some point we turned these into but currently we don't so\n * I'm just going to cement what we do now in Chrome and FF\n */str=str.replace(NEWLINES,' ');var hasLink=false;// as we're building the text, keep track of what elements we're nested inside\n// nodeStack will be an array of {node, type, style, href, target, popup}\n// where only type: 'a' gets the last 3 and node is only added when it's created\nvar nodeStack=[];var currentNode;var currentLine=-1;function newLine(){currentLine++;var lineNode=document.createElementNS(xmlnsNamespaces.svg,'tspan');d3.select(lineNode).attr({class:'line',dy:currentLine*LINE_SPACING+'em'});containerNode.appendChild(lineNode);currentNode=lineNode;var oldNodeStack=nodeStack;nodeStack=[{node:lineNode}];if(oldNodeStack.length>1){for(var i=1;i.',str);return;}var innerNode=nodeStack.pop();if(type!==innerNode.type){Lib.log('Start tag <'+innerNode.type+'> doesnt match end tag <'+type+'>. Pretending it did match.',str);}currentNode=nodeStack[nodeStack.length-1].node;}var hasLines=BR_TAG.test(str);if(hasLines)newLine();else{currentNode=containerNode;nodeStack=[{node:containerNode}];}var parts=str.split(SPLIT_TAGS);for(var i=0;icache.ts+minInterval){exec();return;}cache.timer=setTimeout(function(){exec();cache.timer=null;},minInterval);};exports.done=function(id){var cache=timerCache[id];if(!cache||!cache.timer)return Promise.resolve();return new Promise(function(resolve){var previousOnDone=cache.onDone;cache.onDone=function onDone(){if(previousOnDone)previousOnDone();resolve();cache.onDone=null;};});};/**\n * Clear the throttle cache for one or all timers\n * @param {optional string} id:\n * if provided, clear just this timer\n * if omitted, clear all timers (mainly useful for testing)\n */exports.clear=function(id){if(id){_clearTimeout(timerCache[id]);delete timerCache[id];}else{for(var idi in timerCache)exports.clear(idi);}};function _clearTimeout(cache){if(cache&&cache.timer!==null){clearTimeout(cache.timer);cache.timer=null;}}},{}],761:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var isNumeric=_dereq_('fast-isnumeric');/**\n * convert a linear value into a logged value, folding negative numbers into\n * the given range\n */module.exports=function toLogRange(val,range){if(val>0)return Math.log(val)/Math.LN10;// move a negative value reference to a log axis - just put the\n// result at the lowest range value on the plot (or if the range also went negative,\n// one millionth of the top of the range)\nvar newVal=Math.log(Math.min(range[0],range[1]))/Math.LN10;if(!isNumeric(newVal))newVal=Math.log(Math.max(range[0],range[1]))/Math.LN10-6;return newVal;};},{\"fast-isnumeric\":237}],762:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var topojsonUtils=module.exports={};var locationmodeToLayer=_dereq_('../plots/geo/constants').locationmodeToLayer;var topojsonFeature=_dereq_('topojson-client').feature;topojsonUtils.getTopojsonName=function(geoLayout){return[geoLayout.scope.replace(/ /g,'-'),'_',geoLayout.resolution.toString(),'m'].join('');};topojsonUtils.getTopojsonPath=function(topojsonURL,topojsonName){return topojsonURL+topojsonName+'.json';};topojsonUtils.getTopojsonFeatures=function(trace,topojson){var layer=locationmodeToLayer[trace.locationmode];var obj=topojson.objects[layer];return topojsonFeature(topojson,obj).features;};},{\"../plots/geo/constants\":813,\"topojson-client\":538}],763:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';module.exports={moduleType:'locale',name:'en-US',dictionary:{'Click to enter Colorscale title':'Click to enter Colorscale title'},format:{date:'%m/%d/%Y'}};},{}],764:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';module.exports={moduleType:'locale',name:'en',dictionary:{'Click to enter Colorscale title':'Click to enter Colourscale title'},format:{days:['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],shortDays:['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],months:['January','February','March','April','May','June','July','August','September','October','November','December'],shortMonths:['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],periods:['AM','PM'],dateTime:'%a %b %e %X %Y',date:'%d/%m/%Y',time:'%H:%M:%S',decimal:'.',thousands:',',grouping:[3],currency:['$',''],year:'%Y',month:'%b %Y',dayMonth:'%b %-d',dayMonthYear:'%b %-d, %Y'}};},{}],765:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Registry=_dereq_('../registry');/*\n * containerArrayMatch: does this attribute string point into a\n * layout container array?\n *\n * @param {String} astr: an attribute string, like *annotations[2].text*\n *\n * @returns {Object | false} Returns false if `astr` doesn't match a container\n * array. If it does, returns:\n * {array: {String}, index: {Number}, property: {String}}\n * ie the attribute string for the array, the index within the array (or ''\n * if the whole array) and the property within that (or '' if the whole array\n * or the whole object)\n */module.exports=function containerArrayMatch(astr){var rootContainers=Registry.layoutArrayContainers;var regexpContainers=Registry.layoutArrayRegexes;var rootPart=astr.split('[')[0];var arrayStr;var match;// look for regexp matches first, because they may be nested inside root matches\n// eg updatemenus[i].buttons is nested inside updatemenus\nfor(var i=0;i0){Lib.log('Clearing previous rejected promises from queue.');}gd._promises=[];};// make a few changes to the layout right away\n// before it gets used for anything\n// backward compatibility and cleanup of nonstandard options\nexports.cleanLayout=function(layout){var i,j;if(!layout)layout={};// cannot have (x|y)axis1, numbering goes axis, axis2, axis3...\nif(layout.xaxis1){if(!layout.xaxis)layout.xaxis=layout.xaxis1;delete layout.xaxis1;}if(layout.yaxis1){if(!layout.yaxis)layout.yaxis=layout.yaxis1;delete layout.yaxis1;}if(layout.scene1){if(!layout.scene)layout.scene=layout.scene1;delete layout.scene1;}var axisAttrRegex=(Plots.subplotsRegistry.cartesian||{}).attrRegex;var polarAttrRegex=(Plots.subplotsRegistry.polar||{}).attrRegex;var ternaryAttrRegex=(Plots.subplotsRegistry.ternary||{}).attrRegex;var sceneAttrRegex=(Plots.subplotsRegistry.gl3d||{}).attrRegex;var keys=Object.keys(layout);for(i=0;i tickmode\nif(ax.autotick!==undefined){if(ax.tickmode===undefined){ax.tickmode=ax.autotick?'auto':'linear';}delete ax.autotick;}cleanTitle(ax);}else if(polarAttrRegex&&polarAttrRegex.test(key)){// modifications for polar\nvar polar=layout[key];cleanTitle(polar.radialaxis);}else if(ternaryAttrRegex&&ternaryAttrRegex.test(key)){// modifications for ternary\nvar ternary=layout[key];cleanTitle(ternary.aaxis);cleanTitle(ternary.baxis);cleanTitle(ternary.caxis);}else if(sceneAttrRegex&&sceneAttrRegex.test(key)){// modifications for 3D scenes\nvar scene=layout[key];// clean old Camera coords\nvar cameraposition=scene.cameraposition;if(Array.isArray(cameraposition)&&cameraposition[0].length===4){var rotation=cameraposition[0];var center=cameraposition[1];var radius=cameraposition[2];var mat=m4FromQuat([],rotation);var eye=[];for(j=0;j<3;++j){eye[j]=center[j]+radius*mat[2+4*j];}scene.camera={eye:{x:eye[0],y:eye[1],z:eye[2]},center:{x:center[0],y:center[1],z:center[2]},up:{x:0,y:0,z:1}// we just ignore calculating camera z up in this case\n};delete scene.cameraposition;}// clean axis titles\ncleanTitle(scene.xaxis);cleanTitle(scene.yaxis);cleanTitle(scene.zaxis);}}var annotationsLen=Array.isArray(layout.annotations)?layout.annotations.length:0;for(i=0;i3){legend.x=1.02;legend.xanchor='left';}else if(legend.x<-2){legend.x=-0.02;legend.xanchor='right';}if(legend.y>3){legend.y=1.02;legend.yanchor='bottom';}else if(legend.y<-2){legend.y=-0.02;legend.yanchor='top';}}// clean plot title\ncleanTitle(layout);/*\n * Moved from rotate -> orbit for dragmode\n */if(layout.dragmode==='rotate')layout.dragmode='orbit';// sanitize rgb(fractions) and rgba(fractions) that old tinycolor\n// supported, but new tinycolor does not because they're not valid css\nColor.clean(layout);// clean the layout container in layout.template\nif(layout.template&&layout.template.layout){exports.cleanLayout(layout.template.layout);}return layout;};function cleanAxRef(container,attr){var valIn=container[attr];var axLetter=attr.charAt(0);if(valIn&&valIn!=='paper'){container[attr]=cleanId(valIn,axLetter);}}/**\n * Cleans up old title attribute structure (flat) in favor of the new one (nested).\n *\n * @param {Object} titleContainer - an object potentially including deprecated title attributes\n */function cleanTitle(titleContainer){if(titleContainer){// title -> title.text\n// (although title used to be a string attribute,\n// numbers are accepted as well)\nif(typeof titleContainer.title==='string'||typeof titleContainer.title==='number'){titleContainer.title={text:titleContainer.title};}rewireAttr('titlefont','font');rewireAttr('titleposition','position');rewireAttr('titleside','side');rewireAttr('titleoffset','offset');}function rewireAttr(oldAttrName,newAttrName){var oldAttrSet=titleContainer[oldAttrName];var newAttrSet=titleContainer.title&&titleContainer.title[newAttrName];if(oldAttrSet&&!newAttrSet){// Ensure title object exists\nif(!titleContainer.title){titleContainer.title={};}titleContainer.title[newAttrName]=titleContainer[oldAttrName];delete titleContainer[oldAttrName];}}}/*\n * cleanData: Make a few changes to the data for backward compatibility\n * before it gets used for anything. Modifies the data traces users provide.\n *\n * Important: if you're going to add something here that modifies a data array,\n * update it in place so the new array === the old one.\n */exports.cleanData=function(data){for(var tracei=0;traceiscale, reversescl->reversescale\nif('scl'in trace&&!('colorscale'in trace)){trace.colorscale=trace.scl;delete trace.scl;}if('reversescl'in trace&&!('reversescale'in trace)){trace.reversescale=trace.reversescl;delete trace.reversescl;}// axis ids x1 -> x, y1-> y\nif(trace.xaxis)trace.xaxis=cleanId(trace.xaxis,'x');if(trace.yaxis)trace.yaxis=cleanId(trace.yaxis,'y');// scene ids scene1 -> scene\nif(traceIs(trace,'gl3d')&&trace.scene){trace.scene=Plots.subplotsRegistry.gl3d.cleanId(trace.scene);}if(!traceIs(trace,'pie-like')&&!traceIs(trace,'bar-like')){if(Array.isArray(trace.textposition)){for(i=0;i0)return attr.substr(0,tail);}/*\n * hasParent: does an attribute object contain a parent of the given attribute?\n * for example, given 'images[2].x' do we also have 'images' or 'images[2]'?\n *\n * @param {Object} aobj\n * update object, whose keys are attribute strings and values are their new settings\n * @param {string} attr\n * the attribute string to test against\n * @returns {Boolean}\n * is a parent of attr present in aobj?\n */exports.hasParent=function(aobj,attr){var attrParent=getParent(attr);while(attrParent){if(attrParent in aobj)return true;attrParent=getParent(attrParent);}return false;};/**\n * Empty out types for all axes containing these traces so we auto-set them again\n *\n * @param {object} gd\n * @param {[integer]} traces: trace indices to search for axes to clear the types of\n * @param {object} layoutUpdate: any update being done concurrently to the layout,\n * which may supercede clearing the axis types\n */var axLetters=['x','y','z'];exports.clearAxisTypes=function(gd,traces,layoutUpdate){for(var i=0;i relayout calls -> edits we get here\n * (as prepared in _relayout):\n *\n * add an empty obj -> {'annotations[2]': 'add'} -> {2: {'': 'add'}}\n * add a specific obj -> {'annotations[2]': {attrs}} -> {2: {'': {attrs}}}\n * delete an obj -> {'annotations[2]': 'remove'} -> {2: {'': 'remove'}}\n * -> {'annotations[2]': null} -> {2: {'': null}}\n * delete the whole array -> {'annotations': 'remove'} -> {'': {'': 'remove'}}\n * -> {'annotations': null} -> {'': {'': null}}\n * edit an object -> {'annotations[2].text': 'boo'} -> {2: {'text': 'boo'}}\n *\n * You can combine many edits to different objects. Objects are added and edited\n * in ascending order, then removed in descending order.\n * For example, starting with [a, b, c], if you want to:\n * - replace b with d:\n * {'annotations[1]': d, 'annotations[2]': null} (b is item 2 after adding d)\n * - add a new item d between a and b, and edit b:\n * {'annotations[1]': d, 'annotations[2].x': newX} (b is item 2 after adding d)\n * - delete b and edit c:\n * {'annotations[1]': null, 'annotations[2].x': newX} (c is edited before b is removed)\n *\n * You CANNOT combine adding/deleting an item at index `i` with edits to the same index `i`\n * You CANNOT combine replacing/deleting the whole array with anything else (for the same array).\n *\n * @param {HTMLDivElement} gd\n * the DOM element of the graph container div\n * @param {Lib.nestedProperty} componentType: the array we are editing\n * @param {Object} edits\n * the changes to make; keys are indices to edit, values are themselves objects:\n * {attr: newValue} of changes to make to that index (with add/remove behavior\n * in special values of the empty attr)\n * @param {Object} flags\n * the flags for which actions we're going to perform to display these (and\n * any other) changes. If we're already `recalc`ing, we don't need to redraw\n * individual items\n * @param {function} _nestedProperty\n * a (possibly modified for gui edits) nestedProperty constructor\n * The modified version takes a 3rd argument, for a prefix to the attribute\n * string necessary for storing GUI edits\n *\n * @returns {bool} `true` if it managed to complete drawing of the changes\n * `false` would mean the parent should replot.\n */exports.applyContainerArrayChanges=function applyContainerArrayChanges(gd,np,edits,flags,_nestedProperty){var componentType=np.astr;var supplyComponentDefaults=Registry.getComponentMethod(componentType,'supplyLayoutDefaults');var draw=Registry.getComponentMethod(componentType,'draw');var drawOne=Registry.getComponentMethod(componentType,'drawOne');var replotLater=flags.replot||flags.recalc||supplyComponentDefaults===noop||draw===noop;var layout=gd.layout;var fullLayout=gd._fullLayout;if(edits['']){if(Object.keys(edits).length>1){Loggers.warn('Full array edits are incompatible with other edits',componentType);}var fullVal=edits[''][''];if(isRemoveVal(fullVal))np.set(null);else if(Array.isArray(fullVal))np.set(fullVal);else{Loggers.warn('Unrecognized full array edit value',componentType,fullVal);return true;}if(replotLater)return false;supplyComponentDefaults(layout,fullLayout);draw(gd);return true;}var componentNums=Object.keys(edits).map(Number).sort(sorterAsc);var componentArrayIn=np.get();var componentArray=componentArrayIn||[];// componentArrayFull is used just to keep splices in line between\n// full and input arrays, so private keys can be copied over after\n// redoing supplyDefaults\n// TODO: this assumes componentArray is in gd.layout - which will not be\n// true after we extend this to restyle\nvar componentArrayFull=_nestedProperty(fullLayout,componentType).get();var deletes=[];var firstIndexChange=-1;var maxIndex=componentArray.length;var i;var j;var componentNum;var objEdits;var objKeys;var objVal;var adding,prefix;// first make the add and edit changes\nfor(i=0;icomponentArray.length-(adding?0:1)){Loggers.warn('index out of range',componentType,componentNum);continue;}if(objVal!==undefined){if(objKeys.length>1){Loggers.warn('Insertion & removal are incompatible with edits to the same index.',componentType,componentNum);}if(isRemoveVal(objVal)){deletes.push(componentNum);}else if(adding){if(objVal==='add')objVal={};componentArray.splice(componentNum,0,objVal);if(componentArrayFull)componentArrayFull.splice(componentNum,0,{});}else{Loggers.warn('Unrecognized full object edit value',componentType,componentNum,objVal);}if(firstIndexChange===-1)firstIndexChange=componentNum;}else{for(j=0;j=0;i--){componentArray.splice(deletes[i],1);// TODO: this drops private keys that had been stored in componentArrayFull\n// does this have any ill effects?\nif(componentArrayFull)componentArrayFull.splice(deletes[i],1);}if(!componentArray.length)np.set(null);else if(!componentArrayIn)np.set(componentArray);if(replotLater)return false;supplyComponentDefaults(layout,fullLayout);// finally draw all the components we need to\n// if we added or removed any, redraw all after it\nif(drawOne!==noop){var indicesToDraw;if(firstIndexChange===-1){// there's no re-indexing to do, so only redraw components that changed\nindicesToDraw=componentNums;}else{// in case the component array was shortened, we still need do call\n// drawOne on the latter items so they get properly removed\nmaxIndex=Math.max(componentArray.length,maxIndex);indicesToDraw=[];for(i=0;i=firstIndexChange)break;indicesToDraw.push(componentNum);}for(i=firstIndexChange;i href, used to make robust clipPath URLs\nvar base=d3.select('base');gd._context._baseUrl=base.size()&&base.attr('href')?window.location.href.split('#')[0]:'';}var context=gd._context;var i,keys,key;if(config){keys=Object.keys(config);for(i=0;i=gd.data.length||index<-gd.data.length){throw new Error(arrayName+' must be valid indices for gd.data.');}// check that indices aren't repeated\nif(indices.indexOf(index,i+1)>-1||index>=0&&indices.indexOf(-gd.data.length+index)>-1||index<0&&indices.indexOf(gd.data.length+index)>-1){throw new Error('each index in '+arrayName+' must be unique.');}}}/**\n * Private function used by Plotly.moveTraces to check input args\n *\n * @param gd\n * @param currentIndices\n * @param newIndices\n */function checkMoveTracesArgs(gd,currentIndices,newIndices){// check that gd has attribute 'data' and 'data' is array\nif(!Array.isArray(gd.data)){throw new Error('gd.data must be an array.');}// validate currentIndices array\nif(typeof currentIndices==='undefined'){throw new Error('currentIndices is a required argument.');}else if(!Array.isArray(currentIndices)){currentIndices=[currentIndices];}assertIndexArray(gd,currentIndices,'currentIndices');// validate newIndices array if it exists\nif(typeof newIndices!=='undefined'&&!Array.isArray(newIndices)){newIndices=[newIndices];}if(typeof newIndices!=='undefined'){assertIndexArray(gd,newIndices,'newIndices');}// check currentIndices and newIndices are the same length if newIdices exists\nif(typeof newIndices!=='undefined'&¤tIndices.length!==newIndices.length){throw new Error('current and new indices must be of equal length.');}}/**\n * A private function to reduce the type checking clutter in addTraces.\n *\n * @param gd\n * @param traces\n * @param newIndices\n */function checkAddTracesArgs(gd,traces,newIndices){var i,value;// check that gd has attribute 'data' and 'data' is array\nif(!Array.isArray(gd.data)){throw new Error('gd.data must be an array.');}// make sure traces exists\nif(typeof traces==='undefined'){throw new Error('traces must be defined.');}// make sure traces is an array\nif(!Array.isArray(traces)){traces=[traces];}// make sure each value in traces is an object\nfor(i=0;i=0&&maxp=0&&maxp-1){replace(key,key.replace('titlefont','title.font'));}else if(key.indexOf('titleposition')>-1){replace(key,key.replace('titleposition','title.position'));}else if(key.indexOf('titleside')>-1){replace(key,key.replace('titleside','title.side'));}else if(key.indexOf('titleoffset')>-1){replace(key,key.replace('titleoffset','title.offset'));}}function replace(oldAttrStr,newAttrStr){aobj[newAttrStr]=aobj[oldAttrStr];delete aobj[oldAttrStr];}}/**\n * relayout: update layout attributes of an existing plot\n *\n * Can be called two ways:\n *\n * Signature 1:\n * @param {String | HTMLDivElement} gd\n * the id or dom element of the graph container div\n * @param {String} astr\n * attribute string (like `'xaxis.range[0]'`) to update\n * @param {*} val\n * value to give this attribute\n *\n * Signature 2:\n * @param {String | HTMLDivElement} gd\n * (as in signature 1)\n * @param {Object} aobj\n * attribute object `{astr1: val1, astr2: val2 ...}`\n * allows setting multiple attributes simultaneously\n */function relayout(gd,astr,val){gd=Lib.getGraphDiv(gd);helpers.clearPromiseQueue(gd);if(gd.framework&&gd.framework.isPolar){return Promise.resolve(gd);}var aobj={};if(typeof astr==='string'){aobj[astr]=val;}else if(Lib.isPlainObject(astr)){aobj=Lib.extendFlat({},astr);}else{Lib.warn('Relayout fail.',astr,val);return Promise.reject();}if(Object.keys(aobj).length)gd.changed=true;var specs=_relayout(gd,aobj);var flags=specs.flags;// clear calcdata if required\nif(flags.calc)gd.calcdata=undefined;// fill in redraw sequence\n// even if we don't have anything left in aobj,\n// something may have happened within relayout that we\n// need to wait for\nvar seq=[Plots.previousPromises];if(flags.layoutReplot){seq.push(subroutines.layoutReplot);}else if(Object.keys(aobj).length){axRangeSupplyDefaultsByPass(gd,flags,specs)||Plots.supplyDefaults(gd);if(flags.legend)seq.push(subroutines.doLegend);if(flags.layoutstyle)seq.push(subroutines.layoutStyles);if(flags.axrange)addAxRangeSequence(seq,specs.rangesAltered);if(flags.ticks)seq.push(subroutines.doTicksRelayout);if(flags.modebar)seq.push(subroutines.doModeBar);if(flags.camera)seq.push(subroutines.doCamera);if(flags.colorbars)seq.push(subroutines.doColorBars);seq.push(emitAfterPlot);}seq.push(Plots.rehover,Plots.redrag);Queue.add(gd,relayout,[gd,specs.undoit],relayout,[gd,specs.redoit]);var plotDone=Lib.syncOrAsync(seq,gd);if(!plotDone||!plotDone.then)plotDone=Promise.resolve(gd);return plotDone.then(function(){gd.emit('plotly_relayout',specs.eventData);return gd;});}// Optimization mostly for large splom traces where\n// Plots.supplyDefaults can take > 100ms\nfunction axRangeSupplyDefaultsByPass(gd,flags,specs){var fullLayout=gd._fullLayout;if(!flags.axrange)return false;for(var k in flags){if(k!=='axrange'&&flags[k])return false;}for(var axId in specs.rangesAltered){var axName=Axes.id2name(axId);var axIn=gd.layout[axName];var axOut=fullLayout[axName];axOut.autorange=axIn.autorange;axOut.range=axIn.range.slice();axOut.cleanRange();if(axOut._matchGroup){for(var axId2 in axOut._matchGroup){if(axId2!==axId){var ax2=fullLayout[Axes.id2name(axId2)];ax2.autorange=axOut.autorange;ax2.range=axOut.range.slice();ax2._input.range=axOut.range.slice();}}}}return true;}function addAxRangeSequence(seq,rangesAltered){// N.B. leave as sequence of subroutines (for now) instead of\n// subroutine of its own so that finalDraw always gets\n// executed after drawData\nvar drawAxes=rangesAltered?function(gd){var axIds=[];var skipTitle=true;for(var id in rangesAltered){var ax=Axes.getFromId(gd,id);axIds.push(id);if(ax._matchGroup){for(var id2 in ax._matchGroup){if(!rangesAltered[id2]){axIds.push(id2);}}}if(ax.automargin)skipTitle=false;}return Axes.draw(gd,axIds,{skipTitle:skipTitle});}:function(gd){return Axes.draw(gd,'redraw');};seq.push(clearSelect,subroutines.doAutoRangeAndConstraints,drawAxes,subroutines.drawData,subroutines.finalDraw);}var AX_RANGE_RE=/^[xyz]axis[0-9]*\\.range(\\[[0|1]\\])?$/;var AX_AUTORANGE_RE=/^[xyz]axis[0-9]*\\.autorange$/;var AX_DOMAIN_RE=/^[xyz]axis[0-9]*\\.domain(\\[[0|1]\\])?$/;function _relayout(gd,aobj){var layout=gd.layout;var fullLayout=gd._fullLayout;var guiEditFlag=fullLayout._guiEditing;var layoutNP=makeNP(fullLayout._preGUI,guiEditFlag);var keys=Object.keys(aobj);var axes=Axes.list(gd);var eventData=Lib.extendDeepAll({},aobj);var arrayEdits={};var arrayStr,i,j;cleanDeprecatedAttributeKeys(aobj);keys=Object.keys(aobj);// look for 'allaxes', split out into all axes\n// in case of 3D the axis are nested within a scene which is held in _id\nfor(i=0;i0&&typeof p.parts[pend]!=='string')pend--;// last property in chain (leaf node)\nvar pleaf=p.parts[pend];// leaf plus immediate parent\nvar pleafPlus=p.parts[pend-1]+'.'+pleaf;// trunk nodes (everything except the leaf)\nvar ptrunk=p.parts.slice(0,pend).join('.');var parentIn=nestedProperty(gd.layout,ptrunk).get();var parentFull=nestedProperty(fullLayout,ptrunk).get();var vOld=p.get();if(vi===undefined)continue;redoit[ai]=vi;// axis reverse is special - it is its own inverse\n// op and has no flag.\nundoit[ai]=pleaf==='reverse'?vi:undefinedToNull(vOld);var valObject=PlotSchema.getLayoutValObject(fullLayout,p.parts);if(valObject&&valObject.impliedEdits&&vi!==null){for(var impliedKey in valObject.impliedEdits){doextra(Lib.relativeAttr(ai,impliedKey),valObject.impliedEdits[impliedKey]);}}// Setting width or height to null must reset the graph's width / height\n// back to its initial value as computed during the first pass in Plots.plotAutoSize.\n//\n// To do so, we must manually set them back here using the _initialAutoSize cache.\n// can't use impliedEdits for this because behavior depends on vi\nif(['width','height'].indexOf(ai)!==-1){if(vi){doextra('autosize',null);// currently we don't support autosize one dim only - so\n// explicitly set the other one. Note that doextra will\n// ignore this if the same relayout call also provides oppositeAttr\nvar oppositeAttr=ai==='height'?'width':'height';doextra(oppositeAttr,fullLayout[oppositeAttr]);}else{fullLayout[ai]=gd._initialAutoSize[ai];}}else if(ai==='autosize'){// depends on vi here too, so again can't use impliedEdits\ndoextra('width',vi?null:fullLayout.width);doextra('height',vi?null:fullLayout.height);}else if(pleafPlus.match(AX_RANGE_RE)){// check autorange vs range\nrecordAlteredAxis(pleafPlus);nestedProperty(fullLayout,ptrunk+'._inputRange').set(null);}else if(pleafPlus.match(AX_AUTORANGE_RE)){recordAlteredAxis(pleafPlus);nestedProperty(fullLayout,ptrunk+'._inputRange').set(null);var axFull=nestedProperty(fullLayout,ptrunk).get();if(axFull._inputDomain){// if we're autoranging and this axis has a constrained domain,\n// reset it so we don't get locked into a shrunken size\naxFull._input.domain=axFull._inputDomain.slice();}}else if(pleafPlus.match(AX_DOMAIN_RE)){nestedProperty(fullLayout,ptrunk+'._inputDomain').set(null);}// toggling axis type between log and linear: we need to convert\n// positions for components that are still using linearized values,\n// not data values like newer components.\n// previously we did this for log <-> not-log, but now only do it\n// for log <-> linear\nif(pleaf==='type'){var ax=parentIn;var toLog=parentFull.type==='linear'&&vi==='log';var fromLog=parentFull.type==='log'&&vi==='linear';if(toLog||fromLog){if(!ax||!ax.range){// 2D never gets here, but 3D does\n// I don't think this is needed, but left here in case there\n// are edge cases I'm not thinking of.\ndoextra(ptrunk+'.autorange',true);}else if(!parentFull.autorange){// toggling log without autorange: need to also recalculate ranges\n// because log axes use linearized values for range endpoints\nvar r0=ax.range[0];var r1=ax.range[1];if(toLog){// if both limits are negative, autorange\nif(r0<=0&&r1<=0){doextra(ptrunk+'.autorange',true);}// if one is negative, set it 6 orders below the other.\nif(r0<=0)r0=r1/1e6;else if(r1<=0)r1=r0/1e6;// now set the range values as appropriate\ndoextra(ptrunk+'.range[0]',Math.log(r0)/Math.LN10);doextra(ptrunk+'.range[1]',Math.log(r1)/Math.LN10);}else{doextra(ptrunk+'.range[0]',Math.pow(10,r0));doextra(ptrunk+'.range[1]',Math.pow(10,r1));}}else if(toLog){// just make sure the range is positive and in the right\n// order, it'll get recalculated later\nax.range=ax.range[1]>ax.range[0]?[1,2]:[2,1];}// clear polar view initial stash for radial range so that\n// value get recomputed in correct units\nif(Array.isArray(fullLayout._subplots.polar)&&fullLayout._subplots.polar.length&&fullLayout[p.parts[0]]&&p.parts[1]==='radialaxis'){delete fullLayout[p.parts[0]]._subplot.viewInitial['radialaxis.range'];}// Annotations and images also need to convert to/from linearized coords\n// Shapes do not need this :)\nRegistry.getComponentMethod('annotations','convertCoords')(gd,parentFull,vi,doextra);Registry.getComponentMethod('images','convertCoords')(gd,parentFull,vi,doextra);}else{// any other type changes: the range from the previous type\n// will not make sense, so autorange it.\ndoextra(ptrunk+'.autorange',true);doextra(ptrunk+'.range',null);}nestedProperty(fullLayout,ptrunk+'._inputRange').set(null);}else if(pleaf.match(AX_NAME_PATTERN)){var fullProp=nestedProperty(fullLayout,ai).get();var newType=(vi||{}).type;// This can potentially cause strange behavior if the autotype is not\n// numeric (linear, because we don't auto-log) but the previous type\n// was log. That's a very strange edge case though\nif(!newType||newType==='-')newType='linear';Registry.getComponentMethod('annotations','convertCoords')(gd,fullProp,newType,doextra);Registry.getComponentMethod('images','convertCoords')(gd,fullProp,newType,doextra);}// alter gd.layout\n// collect array component edits for execution all together\n// so we can ensure consistent behavior adding/removing items\n// and order-independence for add/remove/edit all together in\n// one relayout call\nvar containerArrayMatch=manageArrays.containerArrayMatch(ai);if(containerArrayMatch){arrayStr=containerArrayMatch.array;i=containerArrayMatch.index;var propStr=containerArrayMatch.property;var updateValObject=valObject||{editType:'calc'};if(i!==''&&propStr===''){// special handling of undoit if we're adding or removing an element\n// ie 'annotations[2]' which can be {...} (add) or null,\n// does not work when replacing the entire array\nif(manageArrays.isAddVal(vi)){undoit[ai]=null;}else if(manageArrays.isRemoveVal(vi)){undoit[ai]=(nestedProperty(layout,arrayStr).get()||[])[i];}else{Lib.warn('unrecognized full object value',aobj);}}editTypes.update(flags,updateValObject);// prepare the edits object we'll send to applyContainerArrayChanges\nif(!arrayEdits[arrayStr])arrayEdits[arrayStr]={};var objEdits=arrayEdits[arrayStr][i];if(!objEdits)objEdits=arrayEdits[arrayStr][i]={};objEdits[propStr]=vi;delete aobj[ai];}else if(pleaf==='reverse'){// handle axis reversal explicitly, as there's no 'reverse' attribute\nif(parentIn.range)parentIn.range.reverse();else{doextra(ptrunk+'.autorange',true);parentIn.range=[1,0];}if(parentFull.autorange)flags.calc=true;else flags.plot=true;}else{if(fullLayout._has('scatter-like')&&fullLayout._has('regl')&&ai==='dragmode'&&(vi==='lasso'||vi==='select')&&!(vOld==='lasso'||vOld==='select')){flags.plot=true;}else if(fullLayout._has('gl2d')){flags.plot=true;}else if(valObject)editTypes.update(flags,valObject);else flags.calc=true;p.set(vi);}}// now we've collected component edits - execute them all together\nfor(arrayStr in arrayEdits){var finished=manageArrays.applyContainerArrayChanges(gd,layoutNP(layout,arrayStr),arrayEdits[arrayStr],flags,layoutNP);if(!finished)flags.plot=true;}// figure out if we need to recalculate axis constraints\nvar constraints=fullLayout._axisConstraintGroups||[];for(axId in rangesAltered){for(i=0;i1){parts.pop();newRev=nestedProperty(container,parts.join('.')+'.uirevision').get();if(newRev!==undefined)return newRev;}return container.uirevision;}function getFullTraceIndexFromUid(uid,fullData){for(var i=0;i=transitionOpts.length){return transitionOpts[0];}else{return transitionOpts[i];}}else{return transitionOpts;}}function getFrameOpts(i){if(Array.isArray(frameOpts)){if(i>=frameOpts.length){return frameOpts[0];}else{return frameOpts[i];}}else{return frameOpts;}}// Execute a callback after the wrapper function has been called n times.\n// This is used to defer the resolution until a transition has resovled *and*\n// the frame has completed. If it's not done this way, then we get a race\n// condition in which the animation might resolve before a transition is complete\n// or vice versa.\nfunction callbackOnNthTime(cb,n){var cnt=0;return function(){if(cb&&++cnt===n){return cb();}};}return new Promise(function(resolve,reject){function discardExistingFrames(){if(trans._frameQueue.length===0){return;}while(trans._frameQueue.length){var next=trans._frameQueue.pop();if(next.onInterrupt){next.onInterrupt();}}gd.emit('plotly_animationinterrupted',[]);}function queueFrames(frameList){if(frameList.length===0)return;for(var i=0;itrans._timeToNext){nextFrame();}};doFrame();}// This is an animate-local counter that helps match up option input list\n// items with the particular frame.\nvar configCounter=0;function setTransitionConfig(frame){if(Array.isArray(transitionOpts)){if(configCounter>=transitionOpts.length){frame.transitionOpts=transitionOpts[configCounter];}else{frame.transitionOpts=transitionOpts[0];}}else{frame.transitionOpts=transitionOpts;}configCounter++;return frame;}// Disambiguate what's sort of frames have been received\nvar i,frame;var frameList=[];var allFrames=frameOrGroupNameOrFrameList===undefined||frameOrGroupNameOrFrameList===null;var isFrameArray=Array.isArray(frameOrGroupNameOrFrameList);var isSingleFrame=!allFrames&&!isFrameArray&&Lib.isPlainObject(frameOrGroupNameOrFrameList);if(isSingleFrame){// In this case, a simple object has been passed to animate.\nframeList.push({type:'object',data:setTransitionConfig(Lib.extendFlat({},frameOrGroupNameOrFrameList))});}else if(allFrames||['string','number'].indexOf(typeof frameOrGroupNameOrFrameList)!==-1){// In this case, null or undefined has been passed so that we want to\n// animate *all* currently defined frames\nfor(i=0;i0&&idxidx){filteredFrameList.push(frame);}}frameList=filteredFrameList;}}if(frameList.length>0){queueFrames(frameList);}else{// This is the case where there were simply no frames. It's a little strange\n// since there's not much to do:\ngd.emit('plotly_animated');resolve();}});}/**\n * Register new frames\n *\n * @param {string id or DOM element} gd\n * the id or DOM element of the graph container div\n *\n * @param {array of objects} frameList\n * list of frame definitions, in which each object includes any of:\n * - name: {string} name of frame to add\n * - data: {array of objects} trace data\n * - layout {object} layout definition\n * - traces {array} trace indices\n * - baseframe {string} name of frame from which this frame gets defaults\n *\n * @param {array of integers} indices\n * an array of integer indices matching the respective frames in `frameList`. If not\n * provided, an index will be provided in serial order. If already used, the frame\n * will be overwritten.\n */function addFrames(gd,frameList,indices){gd=Lib.getGraphDiv(gd);if(frameList===null||frameList===undefined){return Promise.resolve();}if(!Lib.isPlotDiv(gd)){throw new Error('This element is not a Plotly plot: '+gd+'. It\\'s likely that you\\'ve failed '+'to create a plot before adding frames. For more details, see '+'https://plotly.com/javascript/animations/');}var i,frame,j,idx;var _frames=gd._transitionData._frames;var _frameHash=gd._transitionData._frameHash;if(!Array.isArray(frameList)){throw new Error('addFrames failure: frameList must be an Array of frame definitions'+frameList);}// Create a sorted list of insertions since we run into lots of problems if these\n// aren't in ascending order of index:\n//\n// Strictly for sorting. Make sure this is guaranteed to never collide with any\n// already-exisisting indices:\nvar bigIndex=_frames.length+frameList.length*2;var insertions=[];var _frameHashLocal={};for(i=frameList.length-1;i>=0;i--){if(!Lib.isPlainObject(frameList[i]))continue;// The entire logic for checking for this type of name collision can be removed once we migrate to ES6 and\n// use a Map instead of an Object instance, as Map keys aren't converted to strings.\nvar lookupName=frameList[i].name;var name=(_frameHash[lookupName]||_frameHashLocal[lookupName]||{}).name;var newName=frameList[i].name;var collisionPresent=_frameHash[name]||_frameHashLocal[name];if(name&&newName&&typeof newName==='number'&&collisionPresent&&numericNameWarningCountb.index)return-1;if(a.index=0;i--){frame=insertions[i].frame;if(typeof frame.name==='number'){Lib.warn('Warning: addFrames accepts frames with numeric names, but the numbers are'+'implicitly cast to strings');}if(!frame.name){// Repeatedly assign a default name, incrementing the counter each time until\n// we get a name that's not in the hashed lookup table:\nwhile(_frameHash[frame.name='frame '+gd._transitionData._counter++]);}if(_frameHash[frame.name]){// If frame is present, overwrite its definition:\nfor(j=0;j<_frames.length;j++){if((_frames[j]||{}).name===frame.name)break;}ops.push({type:'replace',index:j,value:frame});revops.unshift({type:'replace',index:j,value:_frames[j]});}else{// Otherwise insert it at the end of the list:\nidx=Math.max(0,Math.min(insertions[i].index,frameCount));ops.push({type:'insert',index:idx,value:frame});revops.unshift({type:'delete',index:idx});frameCount++;}}var undoFunc=Plots.modifyFrames;var redoFunc=Plots.modifyFrames;var undoArgs=[gd,revops];var redoArgs=[gd,ops];if(Queue)Queue.add(gd,undoFunc,undoArgs,redoFunc,redoArgs);return Plots.modifyFrames(gd,ops);}/**\n * Delete frame\n *\n * @param {string id or DOM element} gd\n * the id or DOM element of the graph container div\n *\n * @param {array of integers} frameList\n * list of integer indices of frames to be deleted\n */function deleteFrames(gd,frameList){gd=Lib.getGraphDiv(gd);if(!Lib.isPlotDiv(gd)){throw new Error('This element is not a Plotly plot: '+gd);}var i,idx;var _frames=gd._transitionData._frames;var ops=[];var revops=[];if(!frameList){frameList=[];for(i=0;i<_frames.length;i++){frameList.push(i);}}frameList=frameList.slice();frameList.sort();for(i=frameList.length-1;i>=0;i--){idx=frameList[i];ops.push({type:'delete',index:idx});revops.unshift({type:'insert',index:idx,value:_frames[idx]});}var undoFunc=Plots.modifyFrames;var redoFunc=Plots.modifyFrames;var undoArgs=[gd,revops];var redoArgs=[gd,ops];if(Queue)Queue.add(gd,undoFunc,undoArgs,redoFunc,redoArgs);return Plots.modifyFrames(gd,ops);}/**\n * Purge a graph container div back to its initial pre-Plotly.plot state\n *\n * @param {string id or DOM element} gd\n * the id or DOM element of the graph container div\n */function purge(gd){gd=Lib.getGraphDiv(gd);var fullLayout=gd._fullLayout||{};var fullData=gd._fullData||[];// remove gl contexts\nPlots.cleanPlot([],{},fullData,fullLayout);// purge properties\nPlots.purge(gd);// purge event emitter methods\nEvents.purge(gd);// remove plot container\nif(fullLayout._container)fullLayout._container.remove();// in contrast to Plotly.Plots.purge which does NOT clear _context!\ndelete gd._context;return gd;}// -------------------------------------------------------\n// makePlotFramework: Create the plot container and axes\n// -------------------------------------------------------\nfunction makePlotFramework(gd){var gd3=d3.select(gd);var fullLayout=gd._fullLayout;// Plot container\nfullLayout._container=gd3.selectAll('.plot-container').data([0]);fullLayout._container.enter().insert('div',':first-child').classed('plot-container',true).classed('plotly',true);// Make the svg container\nfullLayout._paperdiv=fullLayout._container.selectAll('.svg-container').data([0]);fullLayout._paperdiv.enter().append('div').classed('svg-container',true).style('position','relative');// Make the graph containers\n// start fresh each time we get here, so we know the order comes out\n// right, rather than enter/exit which can muck up the order\n// TODO: sort out all the ordering so we don't have to\n// explicitly delete anything\n// FIXME: parcoords reuses this object, not the best pattern\nfullLayout._glcontainer=fullLayout._paperdiv.selectAll('.gl-container').data([{}]);fullLayout._glcontainer.enter().append('div').classed('gl-container',true);fullLayout._paperdiv.selectAll('.main-svg').remove();fullLayout._paperdiv.select('.modebar-container').remove();fullLayout._paper=fullLayout._paperdiv.insert('svg',':first-child').classed('main-svg',true);fullLayout._toppaper=fullLayout._paperdiv.append('svg').classed('main-svg',true);fullLayout._modebardiv=fullLayout._paperdiv.append('div');fullLayout._hoverpaper=fullLayout._paperdiv.append('svg').classed('main-svg',true);if(!fullLayout._uid){var otherUids={};d3.selectAll('defs').each(function(){if(this.id)otherUids[this.id.split('-')[1]]=1;});fullLayout._uid=Lib.randstr(otherUids);}fullLayout._paperdiv.selectAll('.main-svg').attr(xmlnsNamespaces.svgAttrs);fullLayout._defs=fullLayout._paper.append('defs').attr('id','defs-'+fullLayout._uid);fullLayout._clips=fullLayout._defs.append('g').classed('clips',true);fullLayout._topdefs=fullLayout._toppaper.append('defs').attr('id','topdefs-'+fullLayout._uid);fullLayout._topclips=fullLayout._topdefs.append('g').classed('clips',true);fullLayout._bgLayer=fullLayout._paper.append('g').classed('bglayer',true);fullLayout._draggers=fullLayout._paper.append('g').classed('draglayer',true);// lower shape/image layer - note that this is behind\n// all subplots data/grids but above the backgrounds\n// except inset subplots, whose backgrounds are drawn\n// inside their own group so that they appear above\n// the data for the main subplot\n// lower shapes and images which are fully referenced to\n// a subplot still get drawn within the subplot's group\n// so they will work correctly on insets\nvar layerBelow=fullLayout._paper.append('g').classed('layer-below',true);fullLayout._imageLowerLayer=layerBelow.append('g').classed('imagelayer',true);fullLayout._shapeLowerLayer=layerBelow.append('g').classed('shapelayer',true);// single cartesian layer for the whole plot\nfullLayout._cartesianlayer=fullLayout._paper.append('g').classed('cartesianlayer',true);// single polar layer for the whole plot\nfullLayout._polarlayer=fullLayout._paper.append('g').classed('polarlayer',true);// single ternary layer for the whole plot\nfullLayout._ternarylayer=fullLayout._paper.append('g').classed('ternarylayer',true);// single geo layer for the whole plot\nfullLayout._geolayer=fullLayout._paper.append('g').classed('geolayer',true);// single funnelarea layer for the whole plot\nfullLayout._funnelarealayer=fullLayout._paper.append('g').classed('funnelarealayer',true);// single pie layer for the whole plot\nfullLayout._pielayer=fullLayout._paper.append('g').classed('pielayer',true);// single treemap layer for the whole plot\nfullLayout._treemaplayer=fullLayout._paper.append('g').classed('treemaplayer',true);// single sunburst layer for the whole plot\nfullLayout._sunburstlayer=fullLayout._paper.append('g').classed('sunburstlayer',true);// single indicator layer for the whole plot\nfullLayout._indicatorlayer=fullLayout._toppaper.append('g').classed('indicatorlayer',true);// fill in image server scrape-svg\nfullLayout._glimages=fullLayout._paper.append('g').classed('glimages',true);// lastly upper shapes, info (legend, annotations) and hover layers go on top\n// these are in a different svg element normally, but get collapsed into a single\n// svg when exporting (after inserting 3D)\n// upper shapes/images are only those drawn above the whole plot, including subplots\nvar layerAbove=fullLayout._toppaper.append('g').classed('layer-above',true);fullLayout._imageUpperLayer=layerAbove.append('g').classed('imagelayer',true);fullLayout._shapeUpperLayer=layerAbove.append('g').classed('shapelayer',true);fullLayout._infolayer=fullLayout._toppaper.append('g').classed('infolayer',true);fullLayout._menulayer=fullLayout._toppaper.append('g').classed('menulayer',true);fullLayout._zoomlayer=fullLayout._toppaper.append('g').classed('zoomlayer',true);fullLayout._hoverlayer=fullLayout._hoverpaper.append('g').classed('hoverlayer',true);// Make the modebar container\nfullLayout._modebardiv.classed('modebar-container',true).style('position','absolute').style('top','0px').style('right','0px');gd.emit('plotly_framework');}exports.animate=animate;exports.addFrames=addFrames;exports.deleteFrames=deleteFrames;exports.addTraces=addTraces;exports.deleteTraces=deleteTraces;exports.extendTraces=extendTraces;exports.moveTraces=moveTraces;exports.prependTraces=prependTraces;exports.newPlot=newPlot;exports.plot=plot;exports.purge=purge;exports.react=react;exports.redraw=redraw;exports.relayout=relayout;exports.restyle=restyle;exports.setPlotConfig=setPlotConfig;exports.update=update;exports._guiRelayout=guiEdit(relayout);exports._guiRestyle=guiEdit(restyle);exports._guiUpdate=guiEdit(update);exports._storeDirectGUIEdit=_storeDirectGUIEdit;},{\"../components/color\":602,\"../components/drawing\":624,\"../constants/xmlns_namespaces\":712,\"../lib\":735,\"../lib/events\":725,\"../lib/queue\":750,\"../lib/svg_text_utils\":759,\"../plots/cartesian/axes\":783,\"../plots/cartesian/constants\":789,\"../plots/cartesian/graph_interact\":792,\"../plots/cartesian/select\":802,\"../plots/plots\":846,\"../plots/polar/legacy\":854,\"../registry\":866,\"./edit_types\":766,\"./helpers\":767,\"./manage_arrays\":769,\"./plot_config\":771,\"./plot_schema\":772,\"./subroutines\":774,\"d3\":165,\"fast-isnumeric\":237,\"has-hover\":413}],771:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';/**\n * This will be transferred over to gd and overridden by\n * config args to Plotly.plot.\n *\n * The defaults are the appropriate settings for plotly.js,\n * so we get the right experience without any config argument.\n *\n * N.B. the config options are not coerced using Lib.coerce so keys\n * like `valType` and `values` are only set for documentation purposes\n * at the moment.\n */var configAttributes={staticPlot:{valType:'boolean',dflt:false},plotlyServerURL:{valType:'string',dflt:''},editable:{valType:'boolean',dflt:false},edits:{annotationPosition:{valType:'boolean',dflt:false},annotationTail:{valType:'boolean',dflt:false},annotationText:{valType:'boolean',dflt:false},axisTitleText:{valType:'boolean',dflt:false},colorbarPosition:{valType:'boolean',dflt:false},colorbarTitleText:{valType:'boolean',dflt:false},legendPosition:{valType:'boolean',dflt:false},legendText:{valType:'boolean',dflt:false},shapePosition:{valType:'boolean',dflt:false},titleText:{valType:'boolean',dflt:false}},autosizable:{valType:'boolean',dflt:false},responsive:{valType:'boolean',dflt:false},fillFrame:{valType:'boolean',dflt:false},frameMargins:{valType:'number',dflt:0,min:0,max:0.5},scrollZoom:{valType:'flaglist',flags:['cartesian','gl3d','geo','mapbox'],extras:[true,false],dflt:'gl3d+geo+mapbox'},doubleClick:{valType:'enumerated',values:[false,'reset','autosize','reset+autosize'],dflt:'reset+autosize'},doubleClickDelay:{valType:'number',dflt:300,min:0},showAxisDragHandles:{valType:'boolean',dflt:true},showAxisRangeEntryBoxes:{valType:'boolean',dflt:true},showTips:{valType:'boolean',dflt:true},showLink:{valType:'boolean',dflt:false},linkText:{valType:'string',dflt:'Edit chart',noBlank:true},sendData:{valType:'boolean',dflt:true},showSources:{valType:'any',dflt:false},displayModeBar:{valType:'enumerated',values:['hover',true,false],dflt:'hover'},showSendToCloud:{valType:'boolean',dflt:false},showEditInChartStudio:{valType:'boolean',dflt:false},modeBarButtonsToRemove:{valType:'any',dflt:[]},modeBarButtonsToAdd:{valType:'any',dflt:[]},modeBarButtons:{valType:'any',dflt:false},toImageButtonOptions:{valType:'any',dflt:{}},displaylogo:{valType:'boolean',dflt:true},watermark:{valType:'boolean',dflt:false},plotGlPixelRatio:{valType:'number',dflt:2,min:1,max:4},setBackground:{valType:'any',dflt:'transparent'},topojsonURL:{valType:'string',noBlank:true,dflt:'https://cdn.plot.ly/'},mapboxAccessToken:{valType:'string',dflt:null},logging:{valType:'integer',min:0,max:2,dflt:1},notifyOnLogging:{valType:'integer',min:0,max:2,dflt:0},queueLength:{valType:'integer',min:0,dflt:0},globalTransforms:{valType:'any',dflt:[]},locale:{valType:'string',dflt:'en-US'},locales:{valType:'any',dflt:{}}};var dfltConfig={};function crawl(src,target){for(var k in src){var obj=src[k];if(obj.valType){target[k]=obj.dflt;}else{if(!target[k]){target[k]={};}crawl(obj,target[k]);}}}crawl(configAttributes,dfltConfig);module.exports={configAttributes:configAttributes,dfltConfig:dfltConfig};},{}],772:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Registry=_dereq_('../registry');var Lib=_dereq_('../lib');var baseAttributes=_dereq_('../plots/attributes');var baseLayoutAttributes=_dereq_('../plots/layout_attributes');var frameAttributes=_dereq_('../plots/frame_attributes');var animationAttributes=_dereq_('../plots/animation_attributes');var configAttributes=_dereq_('./plot_config').configAttributes;// polar attributes are not part of the Registry yet\nvar polarAreaAttrs=_dereq_('../plots/polar/legacy/area_attributes');var polarAxisAttrs=_dereq_('../plots/polar/legacy/axis_attributes');var editTypes=_dereq_('./edit_types');var extendFlat=Lib.extendFlat;var extendDeepAll=Lib.extendDeepAll;var isPlainObject=Lib.isPlainObject;var isArrayOrTypedArray=Lib.isArrayOrTypedArray;var nestedProperty=Lib.nestedProperty;var valObjectMeta=Lib.valObjectMeta;var IS_SUBPLOT_OBJ='_isSubplotObj';var IS_LINKED_TO_ARRAY='_isLinkedToArray';var ARRAY_ATTR_REGEXPS='_arrayAttrRegexps';var DEPRECATED='_deprecated';var UNDERSCORE_ATTRS=[IS_SUBPLOT_OBJ,IS_LINKED_TO_ARRAY,ARRAY_ATTR_REGEXPS,DEPRECATED];exports.IS_SUBPLOT_OBJ=IS_SUBPLOT_OBJ;exports.IS_LINKED_TO_ARRAY=IS_LINKED_TO_ARRAY;exports.DEPRECATED=DEPRECATED;exports.UNDERSCORE_ATTRS=UNDERSCORE_ATTRS;/** Outputs the full plotly.js plot schema\n *\n * @return {object}\n * - defs\n * - traces\n * - layout\n * - transforms\n * - frames\n * - animations\n * - config\n */exports.get=function(){var traces={};Registry.allTypes.concat('area').forEach(function(type){traces[type]=getTraceAttributes(type);});var transforms={};Object.keys(Registry.transformsRegistry).forEach(function(type){transforms[type]=getTransformAttributes(type);});return{defs:{valObjects:valObjectMeta,metaKeys:UNDERSCORE_ATTRS.concat(['description','role','editType','impliedEdits']),editType:{traces:editTypes.traces,layout:editTypes.layout},impliedEdits:{}},traces:traces,layout:getLayoutAttributes(),transforms:transforms,frames:getFramesAttributes(),animation:formatAttributes(animationAttributes),config:formatAttributes(configAttributes)};};/**\n * Crawl the attribute tree, recursively calling a callback function\n *\n * @param {object} attrs\n * The node of the attribute tree (e.g. the root) from which recursion originates\n * @param {Function} callback\n * A callback function with the signature:\n * @callback callback\n * @param {object} attr an attribute\n * @param {String} attrName name string\n * @param {object[]} attrs all the attributes\n * @param {Number} level the recursion level, 0 at the root\n * @param {String} fullAttrString full attribute name (ie 'marker.line')\n * @param {Number} [specifiedLevel]\n * The level in the tree, in order to let the callback function detect descend or backtrack,\n * typically unsupplied (implied 0), just used by the self-recursive call.\n * The necessity arises because the tree traversal is not controlled by callback return values.\n * The decision to not use callback return values for controlling tree pruning arose from\n * the goal of keeping the crawler backwards compatible. Observe that one of the pruning conditions\n * precedes the callback call.\n * @param {string} [attrString]\n * the path to the current attribute, as an attribute string (ie 'marker.line')\n * typically unsupplied, but you may supply it if you want to disambiguate which attrs tree you\n * are starting from\n *\n * @return {object} transformOut\n * copy of transformIn that contains attribute defaults\n */exports.crawl=function(attrs,callback,specifiedLevel,attrString){var level=specifiedLevel||0;attrString=attrString||'';Object.keys(attrs).forEach(function(attrName){var attr=attrs[attrName];if(UNDERSCORE_ATTRS.indexOf(attrName)!==-1)return;var fullAttrString=(attrString?attrString+'.':'')+attrName;callback(attr,attrName,attrs,level,fullAttrString);if(exports.isValObject(attr))return;if(isPlainObject(attr)&&attrName!=='impliedEdits'){exports.crawl(attr,callback,level+1,fullAttrString);}});};/** Is object a value object (or a container object)?\n *\n * @param {object} obj\n * @return {boolean}\n * returns true for a valid value object and\n * false for tree nodes in the attribute hierarchy\n */exports.isValObject=function(obj){return obj&&obj.valType!==undefined;};/**\n * Find all data array attributes in a given trace object - including\n * `arrayOk` attributes.\n *\n * @param {object} trace\n * full trace object that contains a reference to `_module.attributes`\n *\n * @return {array} arrayAttributes\n * list of array attributes for the given trace\n */exports.findArrayAttributes=function(trace){var arrayAttributes=[];var stack=[];var isArrayStack=[];var baseContainer,baseAttrName;function callback(attr,attrName,attrs,level){stack=stack.slice(0,level).concat([attrName]);isArrayStack=isArrayStack.slice(0,level).concat([attr&&attr._isLinkedToArray]);var splittableAttr=attr&&(attr.valType==='data_array'||attr.arrayOk===true)&&!(stack[level-1]==='colorbar'&&(attrName==='ticktext'||attrName==='tickvals'));// Manually exclude 'colorbar.tickvals' and 'colorbar.ticktext' for now\n// which are declared as `valType: 'data_array'` but scale independently of\n// the coordinate arrays.\n//\n// Down the road, we might want to add a schema field (e.g `uncorrelatedArray: true`)\n// to distinguish attributes of the likes.\nif(!splittableAttr)return;crawlIntoTrace(baseContainer,0,'');}function crawlIntoTrace(container,i,astrPartial){var item=container[stack[i]];var newAstrPartial=astrPartial+stack[i];if(i===stack.length-1){if(isArrayOrTypedArray(item)){arrayAttributes.push(baseAttrName+newAstrPartial);}}else{if(isArrayStack[i]){if(Array.isArray(item)){for(var j=0;j=transforms.length){return false;}moduleAttrs=(Registry.transformsRegistry[transforms[tNum].type]||{}).attributes;valObject=moduleAttrs&&moduleAttrs[parts[2]];i=3;// start recursing only inside the transform\n}else if(trace.type==='area'){valObject=polarAreaAttrs[head];}else{// first look in the module for this trace\n// components have already merged their trace attributes in here\nvar _module=trace._module;if(!_module)_module=(Registry.modules[trace.type||baseAttributes.type.dflt]||{})._module;if(!_module)return false;moduleAttrs=_module.attributes;valObject=moduleAttrs&&moduleAttrs[head];// then look in the subplot attributes\nif(!valObject){var subplotModule=_module.basePlotModule;if(subplotModule&&subplotModule.attributes){valObject=subplotModule.attributes[head];}}// finally look in the global attributes\nif(!valObject)valObject=baseAttributes[head];}return recurseIntoValObject(valObject,parts,i);};/*\n * Find the valObject for one layout attribute\n *\n * @param {array} parts\n * an array of parts, like ['annotations', 1, 'x']\n * typically from nestedProperty(...).parts\n *\n * @return {object|false}\n * the valObject for this attribute, or the last found parent\n * in some cases the innermost valObject will not exist, for example\n * `valType: 'any'` attributes where we might set a part of the attribute.\n * In that case, stop at the deepest valObject we *do* find.\n */exports.getLayoutValObject=function(fullLayout,parts){var valObject=layoutHeadAttr(fullLayout,parts[0]);return recurseIntoValObject(valObject,parts,1);};function layoutHeadAttr(fullLayout,head){var i,key,_module,attributes;// look for attributes of the subplot types used on the plot\nvar basePlotModules=fullLayout._basePlotModules;if(basePlotModules){var out;for(i=0;i=items.length)return false;if(valObject.dimensions===2){i++;if(parts.length===i)return valObject;var index2=parts[i];if(!isIndex(index2))return false;valObject=items[index][index2];}else valObject=items[index];}else{valObject=items;}}}return valObject;}// note: this is different from Lib.isIndex, this one doesn't accept numeric\n// strings, only actual numbers.\nfunction isIndex(val){return val===Math.round(val)&&val>=0;}function getTraceAttributes(type){var _module,basePlotModule;if(type==='area'){_module={attributes:polarAreaAttrs};basePlotModule={};}else{_module=Registry.modules[type]._module,basePlotModule=_module.basePlotModule;}var attributes={};// make 'type' the first attribute in the object\nattributes.type=null;var copyBaseAttributes=extendDeepAll({},baseAttributes);var copyModuleAttributes=extendDeepAll({},_module.attributes);// prune global-level trace attributes that are already defined in a trace\nexports.crawl(copyModuleAttributes,function(attr,attrName,attrs,level,fullAttrString){nestedProperty(copyBaseAttributes,fullAttrString).set(undefined);// Prune undefined attributes\nif(attr===undefined)nestedProperty(copyModuleAttributes,fullAttrString).set(undefined);});// base attributes (same for all trace types)\nextendDeepAll(attributes,copyBaseAttributes);// prune-out base attributes based on trace module categories\nif(Registry.traceIs(type,'noOpacity')){delete attributes.opacity;}if(!Registry.traceIs(type,'showLegend')){delete attributes.showlegend;delete attributes.legendgroup;}if(Registry.traceIs(type,'noHover')){delete attributes.hoverinfo;delete attributes.hoverlabel;}if(!_module.selectPoints){delete attributes.selectedpoints;}// module attributes\nextendDeepAll(attributes,copyModuleAttributes);// subplot attributes\nif(basePlotModule.attributes){extendDeepAll(attributes,basePlotModule.attributes);}// 'type' gets overwritten by baseAttributes; reset it here\nattributes.type=type;var out={meta:_module.meta||{},categories:_module.categories||{},animatable:Boolean(_module.animatable),type:type,attributes:formatAttributes(attributes)};// trace-specific layout attributes\nif(_module.layoutAttributes){var layoutAttributes={};extendDeepAll(layoutAttributes,_module.layoutAttributes);out.layoutAttributes=formatAttributes(layoutAttributes);}// drop anim:true in non-animatable modules\nif(!_module.animatable){exports.crawl(out,function(attr){if(exports.isValObject(attr)&&'anim'in attr){delete attr.anim;}});}return out;}function getLayoutAttributes(){var layoutAttributes={};var key,_module;// global layout attributes\nextendDeepAll(layoutAttributes,baseLayoutAttributes);// add base plot module layout attributes\nfor(key in Registry.subplotsRegistry){_module=Registry.subplotsRegistry[key];if(!_module.layoutAttributes)continue;if(Array.isArray(_module.attr)){for(var i=0;i<_module.attr.length;i++){handleBasePlotModule(layoutAttributes,_module,_module.attr[i]);}}else{var astr=_module.attr==='subplot'?_module.name:_module.attr;handleBasePlotModule(layoutAttributes,_module,astr);}}// polar layout attributes\nlayoutAttributes=assignPolarLayoutAttrs(layoutAttributes);// add registered components layout attributes\nfor(key in Registry.componentsRegistry){_module=Registry.componentsRegistry[key];var schema=_module.schema;if(schema&&(schema.subplots||schema.layout)){/*\n * Components with defined schema have already been merged in at register time\n * but a few components define attributes that apply only to xaxis\n * not yaxis (rangeselector, rangeslider) - delete from y schema.\n * Note that the input attributes for xaxis/yaxis are the same object\n * so it's not possible to only add them to xaxis from the start.\n * If we ever have such asymmetry the other way, or anywhere else,\n * we will need to extend both this code and mergeComponentAttrsToSubplot\n * (which will not find yaxis only for example)\n */var subplots=schema.subplots;if(subplots&&subplots.xaxis&&!subplots.yaxis){for(var xkey in subplots.xaxis){delete layoutAttributes.yaxis[xkey];}}}else if(_module.name==='colorscale'){extendDeepAll(layoutAttributes,_module.layoutAttributes);}else if(_module.layoutAttributes){// older style without schema need to be explicitly merged in now\ninsertAttrs(layoutAttributes,_module.layoutAttributes,_module.name);}}return{layoutAttributes:formatAttributes(layoutAttributes)};}function getTransformAttributes(type){var _module=Registry.transformsRegistry[type];var attributes=extendDeepAll({},_module.attributes);// add registered components transform attributes\nObject.keys(Registry.componentsRegistry).forEach(function(k){var _module=Registry.componentsRegistry[k];if(_module.schema&&_module.schema.transforms&&_module.schema.transforms[type]){Object.keys(_module.schema.transforms[type]).forEach(function(v){insertAttrs(attributes,_module.schema.transforms[type][v],v);});}});return{attributes:formatAttributes(attributes)};}function getFramesAttributes(){var attrs={frames:extendDeepAll({},frameAttributes)};formatAttributes(attrs);return attrs.frames;}function formatAttributes(attrs){mergeValTypeAndRole(attrs);formatArrayContainers(attrs);stringify(attrs);return attrs;}function mergeValTypeAndRole(attrs){function makeSrcAttr(attrName){return{valType:'string',editType:'none'};}function callback(attr,attrName,attrs){if(exports.isValObject(attr)){if(attr.valType==='data_array'){// all 'data_array' attrs have role 'data'\nattr.role='data';// all 'data_array' attrs have a corresponding 'src' attr\nattrs[attrName+'src']=makeSrcAttr(attrName);}else if(attr.arrayOk===true){// all 'arrayOk' attrs have a corresponding 'src' attr\nattrs[attrName+'src']=makeSrcAttr(attrName);}}else if(isPlainObject(attr)){// all attrs container objects get role 'object'\nattr.role='object';}}exports.crawl(attrs,callback);}function formatArrayContainers(attrs){function callback(attr,attrName,attrs){if(!attr)return;var itemName=attr[IS_LINKED_TO_ARRAY];if(!itemName)return;delete attr[IS_LINKED_TO_ARRAY];attrs[attrName]={items:{}};attrs[attrName].items[itemName]=attr;attrs[attrName].role='object';}exports.crawl(attrs,callback);}// this can take around 10ms and should only be run from PlotSchema.get(),\n// to ensure JSON.stringify(PlotSchema.get()) gives the intended result.\nfunction stringify(attrs){function walk(attr){for(var k in attr){if(isPlainObject(attr[k])){walk(attr[k]);}else if(Array.isArray(attr[k])){for(var i=0;i {}\nif(attr[k]instanceof RegExp){attr[k]=attr[k].toString();}}}}walk(attrs);}function assignPolarLayoutAttrs(layoutAttributes){extendFlat(layoutAttributes,{radialaxis:polarAxisAttrs.radialaxis,angularaxis:polarAxisAttrs.angularaxis});extendFlat(layoutAttributes,polarAxisAttrs.layout);return layoutAttributes;}function handleBasePlotModule(layoutAttributes,_module,astr){var np=nestedProperty(layoutAttributes,astr);var attrs=extendDeepAll({},_module.layoutAttributes);attrs[IS_SUBPLOT_OBJ]=true;np.set(attrs);}function insertAttrs(baseAttrs,newAttrs,astr){var np=nestedProperty(baseAttrs,astr);np.set(extendDeepAll(np.get()||{},newAttrs));}},{\"../lib\":735,\"../plots/animation_attributes\":778,\"../plots/attributes\":780,\"../plots/frame_attributes\":812,\"../plots/layout_attributes\":837,\"../plots/polar/legacy/area_attributes\":852,\"../plots/polar/legacy/axis_attributes\":853,\"../registry\":866,\"./edit_types\":766,\"./plot_config\":771}],773:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Lib=_dereq_('../lib');var plotAttributes=_dereq_('../plots/attributes');var TEMPLATEITEMNAME='templateitemname';var templateAttrs={name:{valType:'string',editType:'none'}};templateAttrs[TEMPLATEITEMNAME]={valType:'string',editType:'calc'};/**\n * templatedArray: decorate an attributes object with templating (and array)\n * properties.\n *\n * @param {string} name: the singular form of the array name. Sets\n * `_isLinkedToArray` to this, so the schema knows to treat this as an array.\n * @param {object} attrs: the item attributes. Since all callers are expected\n * to be constructing this object on the spot, we mutate it here for\n * performance, rather than extending a new object with it.\n *\n * @returns {object}: the decorated `attrs` object\n */exports.templatedArray=function(name,attrs){attrs._isLinkedToArray=name;attrs.name=templateAttrs.name;attrs[TEMPLATEITEMNAME]=templateAttrs[TEMPLATEITEMNAME];return attrs;};/**\n * traceTemplater: logic for matching traces to trace templates\n *\n * @param {object} dataTemplate: collection of {traceType: [{template}, ...]}\n * ie each type the template applies to contains a list of template objects,\n * to be provided cyclically to data traces of that type.\n *\n * @returns {object}: {newTrace}, a function:\n * newTrace(traceIn): that takes the input traceIn, coerces its type, then\n * uses that type to find the next template to apply. returns the output\n * traceOut with template attached, ready to continue supplyDefaults.\n */exports.traceTemplater=function(dataTemplate){var traceCounts={};var traceType,typeTemplates;for(traceType in dataTemplate){typeTemplates=dataTemplate[traceType];if(Array.isArray(typeTemplates)&&typeTemplates.length){traceCounts[traceType]=0;}}function newTrace(traceIn){traceType=Lib.coerce(traceIn,{},plotAttributes,'type');var traceOut={type:traceType,_template:null};if(traceType in traceCounts){typeTemplates=dataTemplate[traceType];// cycle through traces in the template set for this type\nvar typei=traceCounts[traceType]%typeTemplates.length;traceCounts[traceType]++;traceOut._template=typeTemplates[typei];}else{// TODO: anything we should do for types missing from the template?\n// try to apply some other type? Or just bail as we do here?\n// Actually I think yes, we should apply other types; would be nice\n// if all scatter* could inherit from each other, and if histogram\n// could inherit from bar, etc... but how to specify this? And do we\n// compose them, or if a type is present require it to be complete?\n// Actually this could apply to layout too - 3D annotations\n// inheriting from 2D, axes of different types inheriting from each\n// other...\n}return traceOut;}return{newTrace:newTrace// TODO: function to figure out what's left & what didn't work\n};};/**\n * newContainer: Create a new sub-container inside `container` and propagate any\n * applicable template to it. If there's no template, still propagates\n * `undefined` so relinkPrivate will not retain an old template!\n *\n * @param {object} container: the outer container, should already have _template\n * if there *is* a template for this plot\n * @param {string} name: the key of the new container to make\n * @param {string} baseName: if applicable, a base attribute to take the\n * template from, ie for xaxis3 the base would be xaxis\n *\n * @returns {object}: an object for inclusion _full*, empty except for the\n * appropriate template piece\n */exports.newContainer=function(container,name,baseName){var template=container._template;var part=template&&(template[name]||baseName&&template[baseName]);if(!Lib.isPlainObject(part))part=null;var out=container[name]={_template:part};return out;};/**\n * arrayTemplater: special logic for templating both defaults and specific items\n * in a container array (annotations etc)\n *\n * @param {object} container: the outer container, should already have _template\n * if there *is* a template for this plot\n * @param {string} name: the name of the array to template (ie 'annotations')\n * will be used to find default ('annotationdefaults' object) and specific\n * ('annotations' array) template specs.\n * @param {string} inclusionAttr: the attribute determining this item's\n * inclusion in the output, usually 'visible' or 'enabled'\n *\n * @returns {object}: {newItem, defaultItems}, both functions:\n * newItem(itemIn): create an output item, bare except for the correct\n * template and name(s), as the base for supplyDefaults\n * defaultItems(): to be called after all newItem calls, return any\n * specific template items that have not already beeen included,\n * also as bare output items ready for supplyDefaults.\n */exports.arrayTemplater=function(container,name,inclusionAttr){var template=container._template;var defaultsTemplate=template&&template[arrayDefaultKey(name)];var templateItems=template&&template[name];if(!Array.isArray(templateItems)||!templateItems.length){templateItems=[];}var usedNames={};function newItem(itemIn){// include name and templateitemname in the output object for ALL\n// container array items. Note: you could potentially use different\n// name and templateitemname, if you're using one template to make\n// another template. templateitemname would be the name in the original\n// template, and name is the new \"subclassed\" item name.\nvar out={name:itemIn.name,_input:itemIn};var templateItemName=out[TEMPLATEITEMNAME]=itemIn[TEMPLATEITEMNAME];// no itemname: use the default template\nif(!validItemName(templateItemName)){out._template=defaultsTemplate;return out;}// look for an item matching this itemname\n// note these do not inherit from the default template, only the item.\nfor(var i=0;i=lengthIn&&(itemOut._input||{})._templateitemname;if(templateItemName)index=lengthIn;var itemStr=containerStr+'['+index+']';var update;function resetUpdate(){update={};if(templateItemName){update[itemStr]={};update[itemStr][TEMPLATEITEMNAME]=templateItemName;}}resetUpdate();function modifyBase(attr,value){update[attr]=value;}function modifyItem(attr,value){if(templateItemName){// we're making a new object: edit that object\nLib.nestedProperty(update[itemStr],attr).set(value);}else{// we're editing an existing object: include *just* the edit\nupdate[itemStr+'.'+attr]=value;}}function getUpdateObj(){var updateOut=update;resetUpdate();return updateOut;}function applyUpdate(attr,value){if(attr)modifyItem(attr,value);var updateToApply=getUpdateObj();for(var key in updateToApply){Lib.nestedProperty(parentIn,key).set(updateToApply[key]);}}return{modifyBase:modifyBase,modifyItem:modifyItem,getUpdateObj:getUpdateObj,applyUpdate:applyUpdate};};},{\"../lib\":735,\"../plots/attributes\":780}],774:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var d3=_dereq_('d3');var Registry=_dereq_('../registry');var Plots=_dereq_('../plots/plots');var Lib=_dereq_('../lib');var clearGlCanvases=_dereq_('../lib/clear_gl_canvases');var Color=_dereq_('../components/color');var Drawing=_dereq_('../components/drawing');var Titles=_dereq_('../components/titles');var ModeBar=_dereq_('../components/modebar');var Axes=_dereq_('../plots/cartesian/axes');var alignmentConstants=_dereq_('../constants/alignment');var axisConstraints=_dereq_('../plots/cartesian/constraints');var enforceAxisConstraints=axisConstraints.enforce;var cleanAxisConstraints=axisConstraints.clean;var doAutoRange=_dereq_('../plots/cartesian/autorange').doAutoRange;var SVG_TEXT_ANCHOR_START='start';var SVG_TEXT_ANCHOR_MIDDLE='middle';var SVG_TEXT_ANCHOR_END='end';exports.layoutStyles=function(gd){return Lib.syncOrAsync([Plots.doAutoMargin,lsInner],gd);};function overlappingDomain(xDomain,yDomain,domains){for(var i=0;i=xDomain[1]||existingX[1]<=xDomain[0]){continue;}if(existingY[0]yDomain[0]){return true;}}return false;}function lsInner(gd){var fullLayout=gd._fullLayout;var gs=fullLayout._size;var pad=gs.p;var axList=Axes.list(gd,'',true);var i,subplot,plotinfo,ax,xa,ya;fullLayout._paperdiv.style({width:gd._context.responsive&&fullLayout.autosize&&!gd._context._hasZeroWidth&&!gd.layout.width?'100%':fullLayout.width+'px',height:gd._context.responsive&&fullLayout.autosize&&!gd._context._hasZeroHeight&&!gd.layout.height?'100%':fullLayout.height+'px'}).selectAll('.main-svg').call(Drawing.setSize,fullLayout.width,fullLayout.height);gd._context.setBackground(gd,fullLayout.paper_bgcolor);exports.drawMainTitle(gd);ModeBar.manage(gd);// _has('cartesian') means SVG specifically, not GL2D - but GL2D\n// can still get here because it makes some of the SVG structure\n// for shared features like selections.\nif(!fullLayout._has('cartesian')){return Plots.previousPromises(gd);}function getLinePosition(ax,counterAx,side){var lwHalf=ax._lw/2;if(ax._id.charAt(0)==='x'){if(!counterAx)return gs.t+gs.h*(1-(ax.position||0))+lwHalf%1;else if(side==='top')return counterAx._offset-pad-lwHalf;return counterAx._offset+counterAx._length+pad+lwHalf;}if(!counterAx)return gs.l+gs.w*(ax.position||0)+lwHalf%1;else if(side==='right')return counterAx._offset+counterAx._length+pad+lwHalf;return counterAx._offset-pad-lwHalf;}// some preparation of axis position info\nfor(i=0;idataCount){errorList.push({code:'unused',traceType:traceType,templateCount:templateCount,dataCount:dataCount});}else if(dataCount>templateCount){errorList.push({code:'reused',traceType:traceType,templateCount:templateCount,dataCount:dataCount});}}}// _template: false is when someone tried to modify an array item\n// but there was no template with matching name\nfunction crawlForMissingTemplates(obj,path){for(var key in obj){if(key.charAt(0)==='_')continue;var val=obj[key];var nextPath=getNextPath(obj,key,path);if(isPlainObject(val)){if(Array.isArray(obj)&&val._template===false&&val.templateitemname){errorList.push({code:'missing',path:nextPath,templateitemname:val.templateitemname});}crawlForMissingTemplates(val,nextPath);}else if(Array.isArray(val)&&hasPlainObject(val)){crawlForMissingTemplates(val,nextPath);}}}crawlForMissingTemplates({data:fullData,layout:fullLayout},'');if(errorList.length)return errorList.map(format);};function hasPlainObject(arr){for(var i=0;i\n * or an id to an existing graph \n * @param {object} opts (see above)\n * @return {promise}\n */function toImage(gd,opts){opts=opts||{};var data;var layout;var config;var fullLayout;if(Lib.isPlainObject(gd)){data=gd.data||[];layout=gd.layout||{};config=gd.config||{};fullLayout={};}else{gd=Lib.getGraphDiv(gd);data=Lib.extendDeep([],gd.data);layout=Lib.extendDeep({},gd.layout);config=gd._context;fullLayout=gd._fullLayout||{};}function isImpliedOrValid(attr){return!(attr in opts)||Lib.validate(opts[attr],attrs[attr]);}if(!isImpliedOrValid('width')&&opts.width!==null||!isImpliedOrValid('height')&&opts.height!==null){throw new Error('Height and width should be pixel values.');}if(!isImpliedOrValid('format')){throw new Error('Image format is not jpeg, png, svg or webp.');}var fullOpts={};function coerce(attr,dflt){return Lib.coerce(opts,fullOpts,attrs,attr,dflt);}var format=coerce('format');var width=coerce('width');var height=coerce('height');var scale=coerce('scale');var setBackground=coerce('setBackground');var imageDataOnly=coerce('imageDataOnly');// put the cloned div somewhere off screen before attaching to DOM\nvar clonedGd=document.createElement('div');clonedGd.style.position='absolute';clonedGd.style.left='-5000px';document.body.appendChild(clonedGd);// extend layout with image options\nvar layoutImage=Lib.extendFlat({},layout);if(width){layoutImage.width=width;}else if(opts.width===null&&isNumeric(fullLayout.width)){layoutImage.width=fullLayout.width;}if(height){layoutImage.height=height;}else if(opts.height===null&&isNumeric(fullLayout.height)){layoutImage.height=fullLayout.height;}// extend config for static plot\nvar configImage=Lib.extendFlat({},config,{_exportedPlot:true,staticPlot:true,setBackground:setBackground});var redrawFunc=helpers.getRedrawFunc(clonedGd);function wait(){return new Promise(function(resolve){setTimeout(resolve,helpers.getDelay(clonedGd._fullLayout));});}function convert(){return new Promise(function(resolve,reject){var svg=toSVG(clonedGd,format,scale);var width=clonedGd._fullLayout.width;var height=clonedGd._fullLayout.height;function cleanup(){plotApi.purge(clonedGd);document.body.removeChild(clonedGd);}if(format==='full-json'){var json=plots.graphJson(clonedGd,false,'keepdata','object',true,true);json.version=version;json=JSON.stringify(json);cleanup();if(imageDataOnly){return resolve(json);}else{return resolve(helpers.encodeJSON(json));}}cleanup();if(format==='svg'){if(imageDataOnly){return resolve(svg);}else{return resolve(helpers.encodeSVG(svg));}}var canvas=document.createElement('canvas');canvas.id=Lib.randstr();svgToImg({format:format,width:width,height:height,scale:scale,canvas:canvas,svg:svg,// ask svgToImg to return a Promise\n// rather than EventEmitter\n// leave EventEmitter for backward\n// compatibility\npromise:true}).then(resolve).catch(reject);});}function urlToImageData(url){if(imageDataOnly){return url.replace(helpers.IMAGE_URL_PREFIX,'');}else{return url;}}return new Promise(function(resolve,reject){plotApi.plot(clonedGd,data,layoutImage,configImage).then(redrawFunc).then(wait).then(convert).then(function(url){resolve(urlToImageData(url));}).catch(function(err){reject(err);});});}module.exports=toImage;},{\"../lib\":735,\"../plots/plots\":846,\"../snapshot/helpers\":870,\"../snapshot/svgtoimg\":872,\"../snapshot/tosvg\":874,\"../version\":1322,\"./plot_api\":770,\"fast-isnumeric\":237}],777:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Lib=_dereq_('../lib');var Plots=_dereq_('../plots/plots');var PlotSchema=_dereq_('./plot_schema');var dfltConfig=_dereq_('./plot_config').dfltConfig;var isPlainObject=Lib.isPlainObject;var isArray=Array.isArray;var isArrayOrTypedArray=Lib.isArrayOrTypedArray;/**\n * Validate a data array and layout object.\n *\n * @param {array} data\n * @param {object} layout\n *\n * @return {array} array of error objects each containing:\n * - {string} code\n * error code ('object', 'array', 'schema', 'unused', 'invisible' or 'value')\n * - {string} container\n * container where the error occurs ('data' or 'layout')\n * - {number} trace\n * trace index of the 'data' container where the error occurs\n * - {array} path\n * nested path to the key that causes the error\n * - {string} astr\n * attribute string variant of 'path' compatible with Plotly.restyle and\n * Plotly.relayout.\n * - {string} msg\n * error message (shown in console in logger config argument is enable)\n */module.exports=function validate(data,layout){var schema=PlotSchema.get();var errorList=[];var gd={_context:Lib.extendFlat({},dfltConfig)};var dataIn,layoutIn;if(isArray(data)){gd.data=Lib.extendDeep([],data);dataIn=data;}else{gd.data=[];dataIn=[];errorList.push(format('array','data'));}if(isPlainObject(layout)){gd.layout=Lib.extendDeep({},layout);layoutIn=layout;}else{gd.layout={};layoutIn={};if(arguments.length>1){errorList.push(format('object','layout'));}}// N.B. dataIn and layoutIn are in general not the same as\n// gd.data and gd.layout after supplyDefaults as some attributes\n// in gd.data and gd.layout (still) get mutated during this step.\nPlots.supplyDefaults(gd);var dataOut=gd._fullData;var len=dataIn.length;for(var i=0;i
valOut.length){list.push(format('unused',base,p.concat(valOut.length)));}var len=valOut.length;var arrayItems=Array.isArray(items);if(arrayItems)len=Math.min(len,items.length);var m,n,item,valInPart,valOutPart;if(nestedSchema.dimensions===2){for(n=0;nvalOut[n].length){list.push(format('unused',base,p.concat(n,valOut[n].length)));}var len2=valOut[n].length;for(m=0;m<(arrayItems?Math.min(len2,items[n].length):len2);m++){item=arrayItems?items[n][m]:items;valInPart=valIn[n][m];valOutPart=valOut[n][m];if(!Lib.validate(valInPart,item)){list.push(format('value',base,p.concat(n,m),valInPart));}else if(valOutPart!==valInPart&&valOutPart!==+valInPart){list.push(format('dynamic',base,p.concat(n,m),valInPart,valOutPart));}}}else{list.push(format('array',base,p.concat(n),valIn[n]));}}}else{for(n=0;n0){dp=axLen-getPad(minpt)-getPad(maxpt);if(dp>minSpan){if(dv/dp>mbest){minbest=minpt;maxbest=maxpt;mbest=dv/dp;}}else if(dv/axLen>mbest){// in case of padding longer than the axis\n// at least include the unpadded data values.\nminbest={val:minpt.val,pad:0};maxbest={val:maxpt.val,pad:0};mbest=dv/axLen;}}}}function getMaxPad(prev,pt){return Math.max(prev,getPad(pt));}if(minmin===maxmax){var lower=minmin-1;var upper=minmin+1;if(toZero){if(minmin===0){// The only value we have on this axis is 0, and we want to\n// autorange so zero is one end.\n// In principle this could be [0, 1] or [-1, 0] but usually\n// 'tozero' pins 0 to the low end, so follow that.\nnewRange=[0,1];}else{var maxPad=(minmin>0?maxArray:minArray).reduce(getMaxPad,0);// we're pushing a single value away from the edge due to its\n// padding, with the other end clamped at zero\n// 0.5 means don't push it farther than the center.\nvar rangeEnd=minmin/(1-Math.min(0.5,maxPad/axLen));newRange=minmin>0?[0,rangeEnd]:[rangeEnd,0];}}else if(nonNegative){newRange=[Math.max(0,lower),Math.max(1,upper)];}else{newRange=[lower,upper];}}else{if(toZero){if(minbest.val>=0){minbest={val:0,pad:0};}if(maxbest.val<=0){maxbest={val:0,pad:0};}}else if(nonNegative){if(minbest.val-mbest*getPad(minbest)<0){minbest={val:0,pad:0};}if(maxbest.val<=0){maxbest={val:1,pad:0};}}// in case it changed again...\nmbest=(maxbest.val-minbest.val-calcBreaksLength(minpt.val,maxpt.val))/(axLen-getPad(minbest)-getPad(maxbest));newRange=[minbest.val-mbest*getPad(minbest),maxbest.val+mbest*getPad(maxbest)];}// maintain reversal\nif(axReverse)newRange.reverse();return Lib.simpleMap(newRange,ax.l2r||Number);}/*\n * calculate the pixel padding for ax._min and ax._max entries with\n * optional extrapad as 5% of the total axis length\n */function makePadFn(ax){// 5% padding for points that specify extrapad: true\nvar extrappad=ax._length/20;// domain-constrained axes: base extrappad on the unconstrained\n// domain so it's consistent as the domain changes\nif(ax.constrain==='domain'&&ax._inputDomain){extrappad*=(ax._inputDomain[1]-ax._inputDomain[0])/(ax.domain[1]-ax.domain[0]);}return function getPad(pt){return pt.pad+(pt.extrapad?extrappad:0);};}function concatExtremes(gd,ax){var axId=ax._id;var fullData=gd._fullData;var fullLayout=gd._fullLayout;var minArray=[];var maxArray=[];var i,j,d;function _concat(cont,indices){for(i=0;i0?opts.ppadplus:opts.ppadminus)||opts.ppad||0);var ppadminus=makePadAccessor((ax._m>0?opts.ppadminus:opts.ppadplus)||opts.ppad||0);var vpadplus=makePadAccessor(opts.vpadplus||opts.vpad);var vpadminus=makePadAccessor(opts.vpadminus||opts.vpad);if(!hasArrayOption){// with no arrays other than `data` we don't need to consider\n// every point, only the extreme data points\nvmin=Infinity;vmax=-Infinity;if(isLog){for(i=0;i0)vmin=v;if(v>vmax&&v-FP_SAFE)vmin=v;if(v>vmax&&v=iMax;i--)addItem(i);return{min:minArray,max:maxArray,opts:opts};}function collapseMinArray(array,newVal,newPad,opts){collapseArray(array,newVal,newPad,opts,lessOrEqual);}function collapseMaxArray(array,newVal,newPad,opts){collapseArray(array,newVal,newPad,opts,greaterOrEqual);}/**\n * collapseArray\n *\n * Takes items from 'array' and compares them to 'newVal', 'newPad'.\n *\n * @param {array} array:\n * current set of min or max extremes\n * @param {number} newVal:\n * new value to compare against\n * @param {number} newPad:\n * pad value associated with 'newVal'\n * @param {object} opts:\n * - tozero {boolean}\n * - extrapad {number}\n * @param {function} atLeastAsExtreme:\n * comparison function, use\n * - lessOrEqual for min 'array' and\n * - greaterOrEqual for max 'array'\n *\n * In practice, 'array' is either\n * - 'extremes[ax._id].min' or\n * - 'extremes[ax._id].max\n * found in traces and layout items that affect autorange.\n *\n * Since we don't yet know the relationship between pixels and values\n * (that's what we're trying to figure out!) AND we don't yet know how\n * many pixels `extrapad` represents (it's going to be 5% of the length,\n * but we don't want to have to redo calc just because length changed)\n * two point must satisfy three criteria simultaneously for one to supersede the other:\n * - at least as extreme a `val`\n * - at least as big a `pad`\n * - an unpadded point cannot supersede a padded point, but any other combination can\n *\n * Then:\n * - If the item supersedes the new point, set includeThis false\n * - If the new pt supersedes the item, delete it from 'array'\n */function collapseArray(array,newVal,newPad,opts,atLeastAsExtreme){var tozero=opts.tozero;var extrapad=opts.extrapad;var includeThis=true;for(var j=0;j=newPad&&(v.extrapad||!extrapad)){includeThis=false;break;}else if(atLeastAsExtreme(newVal,v.val)&&v.pad<=newPad&&(extrapad||!v.extrapad)){array.splice(j,1);j--;}}if(includeThis){var clipAtZero=tozero&&newVal===0;array.push({val:newVal,pad:clipAtZero?0:newPad,extrapad:clipAtZero?false:extrapad});}}// In order to stop overflow errors, don't consider points\n// too close to the limits of js floating point\nfunction goodNumber(v){return isNumeric(v)&&Math.abs(v)=v1;}},{\"../../constants/numerical\":711,\"../../lib\":735,\"../../registry\":866,\"fast-isnumeric\":237}],783:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var d3=_dereq_('d3');var isNumeric=_dereq_('fast-isnumeric');var Plots=_dereq_('../../plots/plots');var Registry=_dereq_('../../registry');var Lib=_dereq_('../../lib');var svgTextUtils=_dereq_('../../lib/svg_text_utils');var Titles=_dereq_('../../components/titles');var Color=_dereq_('../../components/color');var Drawing=_dereq_('../../components/drawing');var axAttrs=_dereq_('./layout_attributes');var cleanTicks=_dereq_('./clean_ticks');var constants=_dereq_('../../constants/numerical');var ONEAVGYEAR=constants.ONEAVGYEAR;var ONEAVGMONTH=constants.ONEAVGMONTH;var ONEDAY=constants.ONEDAY;var ONEHOUR=constants.ONEHOUR;var ONEMIN=constants.ONEMIN;var ONESEC=constants.ONESEC;var MINUS_SIGN=constants.MINUS_SIGN;var BADNUM=constants.BADNUM;var alignmentConstants=_dereq_('../../constants/alignment');var MID_SHIFT=alignmentConstants.MID_SHIFT;var CAP_SHIFT=alignmentConstants.CAP_SHIFT;var LINE_SPACING=alignmentConstants.LINE_SPACING;var OPPOSITE_SIDE=alignmentConstants.OPPOSITE_SIDE;var axes=module.exports={};axes.setConvert=_dereq_('./set_convert');var autoType=_dereq_('./axis_autotype');var axisIds=_dereq_('./axis_ids');axes.id2name=axisIds.id2name;axes.name2id=axisIds.name2id;axes.cleanId=axisIds.cleanId;axes.list=axisIds.list;axes.listIds=axisIds.listIds;axes.getFromId=axisIds.getFromId;axes.getFromTrace=axisIds.getFromTrace;var autorange=_dereq_('./autorange');axes.getAutoRange=autorange.getAutoRange;axes.findExtremes=autorange.findExtremes;/*\n * find the list of possible axes to reference with an xref or yref attribute\n * and coerce it to that list\n *\n * attr: the attribute we're generating a reference for. Should end in 'x' or 'y'\n * but can be prefixed, like 'ax' for annotation's arrow x\n * dflt: the default to coerce to, or blank to use the first axis (falling back on\n * extraOption if there is no axis)\n * extraOption: aside from existing axes with this letter, what non-axis value is allowed?\n * Only required if it's different from `dflt`\n */axes.coerceRef=function(containerIn,containerOut,gd,attr,dflt,extraOption){var axLetter=attr.charAt(attr.length-1);var axlist=gd._fullLayout._subplots[axLetter+'axis'];var refAttr=attr+'ref';var attrDef={};if(!dflt)dflt=axlist[0]||extraOption;if(!extraOption)extraOption=dflt;// data-ref annotations are not supported in gl2d yet\nattrDef[refAttr]={valType:'enumerated',values:axlist.concat(extraOption?[extraOption]:[]),dflt:dflt};// xref, yref\nreturn Lib.coerce(containerIn,containerOut,attrDef,refAttr);};/*\n * coerce position attributes (range-type) that can be either on axes or absolute\n * (paper or pixel) referenced. The biggest complication here is that we don't know\n * before looking at the axis whether the value must be a number or not (it may be\n * a date string), so we can't use the regular valType='number' machinery\n *\n * axRef (string): the axis this position is referenced to, or:\n * paper: fraction of the plot area\n * pixel: pixels relative to some starting position\n * attr (string): the attribute in containerOut we are coercing\n * dflt (number): the default position, as a fraction or pixels. If the attribute\n * is to be axis-referenced, this will be converted to an axis data value\n *\n * Also cleans the values, since the attribute definition itself has to say\n * valType: 'any' to handle date axes. This allows us to accept:\n * - for category axes: category names, and convert them here into serial numbers.\n * Note that this will NOT work for axis range endpoints, because we don't know\n * the category list yet (it's set by ax.makeCalcdata during calc)\n * but it works for component (note, shape, images) positions.\n * - for date axes: JS Dates or milliseconds, and convert to date strings\n * - for other types: coerce them to numbers\n */axes.coercePosition=function(containerOut,gd,coerce,axRef,attr,dflt){var cleanPos,pos;if(axRef==='paper'||axRef==='pixel'){cleanPos=Lib.ensureNumber;pos=coerce(attr,dflt);}else{var ax=axes.getFromId(gd,axRef);dflt=ax.fraction2r(dflt);pos=coerce(attr,dflt);cleanPos=ax.cleanPos;}containerOut[attr]=cleanPos(pos);};axes.cleanPosition=function(pos,gd,axRef){var cleanPos=axRef==='paper'||axRef==='pixel'?Lib.ensureNumber:axes.getFromId(gd,axRef).cleanPos;return cleanPos(pos);};axes.redrawComponents=function(gd,axIds){axIds=axIds?axIds:axes.listIds(gd);var fullLayout=gd._fullLayout;function _redrawOneComp(moduleName,methodName,stashName,shortCircuit){var method=Registry.getComponentMethod(moduleName,methodName);var stash={};for(var i=0;i use setConvert method\nif(ax)return{d2c:ax.d2c,c2d:ax.c2d};// special case for 'ids'\n// -> cast to String\nif(d2cTarget==='ids')return{d2c:toString,c2d:toString};// otherwise (e.g. numeric-array of 'marker.color' or 'marker.size')\n// -> cast to Number\nreturn{d2c:toNum,c2d:toNum};};function toNum(v){return+v;}function toString(v){return String(v);}axes.getDataToCoordFunc=function(gd,trace,target,targetArray){return getDataConversions(gd,trace,target,targetArray).d2c;};// get counteraxis letter for this axis (name or id)\n// this can also be used as the id for default counter axis\naxes.counterLetter=function(id){var axLetter=id.charAt(0);if(axLetter==='x')return'y';if(axLetter==='y')return'x';};// incorporate a new minimum difference and first tick into\n// forced\n// note that _forceTick0 is linearized, so needs to be turned into\n// a range value for setting tick0\naxes.minDtick=function(ax,newDiff,newFirst,allow){// doesn't make sense to do forced min dTick on log or category axes,\n// and the plot itself may decide to cancel (ie non-grouped bars)\nif(['log','category','multicategory'].indexOf(ax.type)!==-1||!allow){ax._minDtick=0;}else if(ax._minDtick===undefined){// undefined means there's nothing there yet\nax._minDtick=newDiff;ax._forceTick0=newFirst;}else if(ax._minDtick){if((ax._minDtick/newDiff+1e-6)%1<2e-6&&// existing minDtick is an integer multiple of newDiff\n// (within rounding err)\n// and forceTick0 can be shifted to newFirst\n((newFirst-ax._forceTick0)/newDiff%1+1.000001)%1<2e-6){ax._minDtick=newDiff;ax._forceTick0=newFirst;}else if((newDiff/ax._minDtick+1e-6)%1>2e-6||// if the converse is true (newDiff is a multiple of minDtick and\n// newFirst can be shifted to forceTick0) then do nothing - same\n// forcing stands. Otherwise, cancel forced minimum\n((newFirst-ax._forceTick0)/ax._minDtick%1+1.000001)%1>2e-6){ax._minDtick=0;}}};// save a copy of the initial axis ranges in fullLayout\n// use them in mode bar and dblclick events\naxes.saveRangeInitial=function(gd,overwrite){var axList=axes.list(gd,'',true);var hasOneAxisChanged=false;for(var i=0;i50% within 1% of bin edges) or all data points integral\n// and offset the bins accordingly\nif(typeof finalSize==='number'){binStart=autoShiftNumericBins(binStart,data,dummyAx,dataMin,dataMax);bincount=1+Math.floor((dataMax-binStart)/finalSize);binEnd=binStart+bincount*finalSize;}else{// month ticks - should be the only nonlinear kind we have at this point.\n// dtick (as supplied by axes.autoTick) only has nonlinear values on\n// date and log axes, but even if you display a histogram on a log axis\n// we bin it on a linear axis (which one could argue against, but that's\n// a separate issue)\nif(dummyAx.dtick.charAt(0)==='M'){binStart=autoShiftMonthBins(binStart,data,finalSize,dataMin,calendar);}// calculate the endpoint for nonlinear ticks - you have to\n// just increment until you're done\nbinEnd=binStart;bincount=0;while(binEnd<=dataMax){binEnd=axes.tickIncrement(binEnd,finalSize,false,calendar);bincount++;}}return{start:ax.c2r(binStart,0,calendar),end:ax.c2r(binEnd,0,calendar),size:finalSize,_dataSpan:dataMax-dataMin};};function autoShiftNumericBins(binStart,data,ax,dataMin,dataMax){var edgecount=0;var midcount=0;var intcount=0;var blankCount=0;function nearEdge(v){// is a value within 1% of a bin edge?\nreturn(1+(v-binStart)*100/ax.dtick)%100<2;}for(var i=0;idataCount*0.3||nearEdge(dataMin)||nearEdge(dataMax)){// lots of points at the edge, not many in the middle\n// shift half a bin\nvar binshift=ax.dtick/2;binStart+=binStart+binshiftthreshold){var numMonths=Number(dtick.substr(1));if(stats.exactYears>threshold&&numMonths%12===0){// The exact middle of a non-leap-year is 1.5 days into July\n// so if we start the bins here, all but leap years will\n// get hover-labeled as exact years.\nbinStart=axes.tickIncrement(binStart,'M6','reverse')+ONEDAY*1.5;}else if(stats.exactMonths>threshold){// Months are not as clean, but if we shift half the *longest*\n// month (31/2 days) then 31-day months will get labeled exactly\n// and shorter months will get labeled with the correct month\n// but shifted 12-36 hours into it.\nbinStart=axes.tickIncrement(binStart,'M1','reverse')+ONEDAY*15.5;}else{// Shifting half a day is exact, but since these are month bins it\n// will always give a somewhat odd-looking label, until we do something\n// smarter like showing the bin boundaries (or the bounds of the actual\n// data in each bin)\nbinStart-=ONEDAY/2;}var nextBinStart=axes.tickIncrement(binStart,dtick);if(nextBinStart<=dataMin)return nextBinStart;}return binStart;}// ----------------------------------------------------\n// Ticks and grids\n// ----------------------------------------------------\n// ensure we have tick0, dtick, and tick rounding calculated\naxes.prepTicks=function(ax){var rng=Lib.simpleMap(ax.range,ax.r2l);// calculate max number of (auto) ticks to display based on plot size\nif(ax.tickmode==='auto'||!ax.dtick){var nt=ax.nticks;var minPx;if(!nt){if(ax.type==='category'||ax.type==='multicategory'){minPx=ax.tickfont?(ax.tickfont.size||12)*1.2:15;nt=ax._length/minPx;}else{minPx=ax._id.charAt(0)==='y'?40:80;nt=Lib.constrain(ax._length/minPx,4,9)+1;}// radial axes span half their domain,\n// multiply nticks value by two to get correct number of auto ticks.\nif(ax._name==='radialaxis')nt*=2;}// add a couple of extra digits for filling in ticks when we\n// have explicit tickvals without tick text\nif(ax.tickmode==='array')nt*=100;ax._roughDTick=(Math.abs(rng[1]-rng[0])-(ax._lBreaks||0))/nt;axes.autoTicks(ax,ax._roughDTick);// check for a forced minimum dtick\nif(ax._minDtick>0&&ax.dtick=endTick:x<=endTick;x=axes.tickIncrement(x,ax.dtick,axrev,ax.calendar)){// prevent infinite loops - no more than one tick per pixel,\n// and make sure each value is different from the previous\nif(tickVals.length>maxTicks||x===xPrevious)break;xPrevious=x;var minor=false;if(isDLog&&x!==(x|0)){minor=true;}tickVals.push({minor:minor,value:x});}}generateTicks();if(ax.rangebreaks){// replace ticks inside breaks that would get a tick\nif(ax.tickmode==='auto'){for(var t=0;t=brk.min&&value2){var tf2=2*(ax.tickfont?ax.tickfont.size:12);var newTickVals=[];var prevPos;var dir=axrev?1:-1;var first=axrev?0:len-1;var last=axrev?len-1:0;for(var q=first;dir*q<=dir*last;q+=dir){// apply reverse loop to pick greater values in breaks first\nvar pos=ax.c2p(tickVals[q].value);if(prevPos===undefined||Math.abs(pos-prevPos)>tf2){prevPos=pos;newTickVals.push(tickVals[q]);}}tickVals=newTickVals.reverse();}}// If same angle over a full circle, the last tick vals is a duplicate.\n// TODO must do something similar for angular date axes.\nif(isAngular(ax)&&Math.abs(rng[1]-rng[0])===360){tickVals.pop();}// save the last tick as well as first, so we can\n// show the exponent only on the last one\nax._tmax=(tickVals[tickVals.length-1]||{}).value;// for showing the rest of a date when the main tick label is only the\n// latter part: ax._prevDateHead holds what we showed most recently.\n// Start with it cleared and mark that we're in calcTicks (ie calculating a\n// whole string of these so we should care what the previous date head was!)\nax._prevDateHead='';ax._inCalcTicks=true;var ticksOut=new Array(tickVals.length);for(var i=0;itickMin&&vali half of the final unit - so precalculate twice the rough val\nvar roughX2=2*roughDTick;if(roughX2>ONEAVGYEAR){roughDTick/=ONEAVGYEAR;base=getBase(10);ax.dtick='M'+12*roundDTick(roughDTick,base,roundBase10);}else if(roughX2>ONEAVGMONTH){roughDTick/=ONEAVGMONTH;ax.dtick='M'+roundDTick(roughDTick,1,roundBase24);}else if(roughX2>ONEDAY){ax.dtick=roundDTick(roughDTick,ONEDAY,ax._hasDayOfWeekBreaks?[1,7,14]:roundDays);// get week ticks on sunday\n// this will also move the base tick off 2000-01-01 if dtick is\n// 2 or 3 days... but that's a weird enough case that we'll ignore it.\nax.tick0=Lib.dateTick0(ax.calendar,true);}else if(roughX2>ONEHOUR){ax.dtick=roundDTick(roughDTick,ONEHOUR,roundBase24);}else if(roughX2>ONEMIN){ax.dtick=roundDTick(roughDTick,ONEMIN,roundBase60);}else if(roughX2>ONESEC){ax.dtick=roundDTick(roughDTick,ONESEC,roundBase60);}else{// milliseconds\nbase=getBase(10);ax.dtick=roundDTick(roughDTick,base,roundBase10);}}else if(ax.type==='log'){ax.tick0=0;var rng=Lib.simpleMap(ax.range,ax.r2l);if(roughDTick>0.7){// only show powers of 10\nax.dtick=Math.ceil(roughDTick);}else if(Math.abs(rng[1]-rng[0])<1){// span is less than one power of 10\nvar nt=1.5*Math.abs((rng[1]-rng[0])/roughDTick);// ticks on a linear scale, labeled fully\nroughDTick=Math.abs(Math.pow(10,rng[1])-Math.pow(10,rng[0]))/nt;base=getBase(10);ax.dtick='L'+roundDTick(roughDTick,base,roundBase10);}else{// include intermediates between powers of 10,\n// labeled with small digits\n// ax.dtick = \"D2\" (show 2 and 5) or \"D1\" (show all digits)\nax.dtick=roughDTick>0.3?'D2':'D1';}}else if(ax.type==='category'||ax.type==='multicategory'){ax.tick0=0;ax.dtick=Math.ceil(Math.max(roughDTick,1));}else if(isAngular(ax)){ax.tick0=0;base=1;ax.dtick=roundDTick(roughDTick,base,roundAngles);}else{// auto ticks always start at 0\nax.tick0=0;base=getBase(10);ax.dtick=roundDTick(roughDTick,base,roundBase10);}// prevent infinite loops\nif(ax.dtick===0)ax.dtick=1;// TODO: this is from log axis histograms with autorange off\nif(!isNumeric(ax.dtick)&&typeof ax.dtick!=='string'){var olddtick=ax.dtick;ax.dtick=1;throw'ax.dtick error: '+String(olddtick);}};// after dtick is already known, find tickround = precision\n// to display in tick labels\n// for numeric ticks, integer # digits after . to round to\n// for date ticks, the last date part to show (y,m,d,H,M,S)\n// or an integer # digits past seconds\nfunction autoTickRound(ax){var dtick=ax.dtick;ax._tickexponent=0;if(!isNumeric(dtick)&&typeof dtick!=='string'){dtick=1;}if(ax.type==='category'||ax.type==='multicategory'){ax._tickround=null;}if(ax.type==='date'){// If tick0 is unusual, give tickround a bit more information\n// not necessarily *all* the information in tick0 though, if it's really odd\n// minimal string length for tick0: 'd' is 10, 'M' is 16, 'S' is 19\n// take off a leading minus (year < 0) and i (intercalary month) so length is consistent\nvar tick0ms=ax.r2l(ax.tick0);var tick0str=ax.l2r(tick0ms).replace(/(^-|i)/g,'');var tick0len=tick0str.length;if(String(dtick).charAt(0)==='M'){// any tick0 more specific than a year: alway show the full date\nif(tick0len>10||tick0str.substr(5)!=='01-01')ax._tickround='d';// show the month unless ticks are full multiples of a year\nelse ax._tickround=+dtick.substr(1)%12===0?'y':'m';}else if(dtick>=ONEDAY&&tick0len<=10||dtick>=ONEDAY*15)ax._tickround='d';else if(dtick>=ONEMIN&&tick0len<=16||dtick>=ONEHOUR)ax._tickround='M';else if(dtick>=ONESEC&&tick0len<=19||dtick>=ONEMIN)ax._tickround='S';else{// tickround is a number of digits of fractional seconds\n// of any two adjacent ticks, at least one will have the maximum fractional digits\n// of all possible ticks - so take the max. length of tick0 and the next one\nvar tick1len=ax.l2r(tick0ms+dtick).replace(/^-/,'').length;ax._tickround=Math.max(tick0len,tick1len)-20;// We shouldn't get here... but in case there's a situation I'm\n// not thinking of where tick0str and tick1str are identical or\n// something, fall back on maximum precision\nif(ax._tickround<0)ax._tickround=4;}}else if(isNumeric(dtick)||dtick.charAt(0)==='L'){// linear or log (except D1, D2)\nvar rng=ax.range.map(ax.r2d||Number);if(!isNumeric(dtick))dtick=Number(dtick.substr(1));// 2 digits past largest digit of dtick\nax._tickround=2-Math.floor(Math.log(dtick)/Math.LN10+0.01);var maxend=Math.max(Math.abs(rng[0]),Math.abs(rng[1]));var rangeexp=Math.floor(Math.log(maxend)/Math.LN10+0.01);if(Math.abs(rangeexp)>3){if(isSIFormat(ax.exponentformat)&&!beyondSI(rangeexp)){ax._tickexponent=3*Math.round((rangeexp-1)/3);}else ax._tickexponent=rangeexp;}}else{// D1 or D2 (log)\nax._tickround=null;}}// months and years don't have constant millisecond values\n// (but a year is always 12 months so we only need months)\n// log-scale ticks are also not consistently spaced, except\n// for pure powers of 10\n// numeric ticks always have constant differences, other datetime ticks\n// can all be calculated as constant number of milliseconds\naxes.tickIncrement=function(x,dtick,axrev,calendar){var axSign=axrev?-1:1;// includes linear, all dates smaller than month, and pure 10^n in log\nif(isNumeric(dtick))return x+axSign*dtick;// everything else is a string, one character plus a number\nvar tType=dtick.charAt(0);var dtSigned=axSign*Number(dtick.substr(1));// Dates: months (or years - see Lib.incrementMonth)\nif(tType==='M')return Lib.incrementMonth(x,dtSigned,calendar);// Log scales: Linear, Digits\nelse if(tType==='L')return Math.log(Math.pow(10,x)+dtSigned)/Math.LN10;// log10 of 2,5,10, or all digits (logs just have to be\n// close enough to round)\nelse if(tType==='D'){var tickset=dtick==='D2'?roundLog2:roundLog1;var x2=x+axSign*0.01;var frac=Lib.roundUp(Lib.mod(x2,1),tickset,axrev);return Math.floor(x2)+Math.log(d3.round(Math.pow(10,frac),1))/Math.LN10;}else throw'unrecognized dtick '+String(dtick);};// calculate the first tick on an axis\naxes.tickFirst=function(ax){var r2l=ax.r2l||Number;var rng=Lib.simpleMap(ax.range,r2l);var axrev=rng[1]=0&&p<=ax._length?v:null;};out.xbnd=[inbounds(out.x-0.5),inbounds(out.x+ax.dtick-0.5)];}return out;};/**\n * create text for a hover label on this axis, with special handling of\n * log axes (where negative values can't be displayed but can appear in hover text)\n *\n * @param {object} ax: the axis to format text for\n * @param {number} val: calcdata value to format\n * @param {Optional(number)} val2: a second value to display\n *\n * @returns {string} `val` formatted as a string appropriate to this axis, or\n * `val` and `val2` as a range (ie ' - ') if `val2` is provided and\n * it's different from `val`.\n */axes.hoverLabelText=function(ax,val,val2){if(val2!==BADNUM&&val2!==val){return axes.hoverLabelText(ax,val)+' - '+axes.hoverLabelText(ax,val2);}var logOffScale=ax.type==='log'&&val<=0;var tx=axes.tickText(ax,ax.c2l(logOffScale?-val:val),'hover').text;if(logOffScale){return val===0?'0':MINUS_SIGN+tx;}// TODO: should we do something special if the axis calendar and\n// the data calendar are different? Somehow display both dates with\n// their system names? Right now it will just display in the axis calendar\n// but users could add the other one as text.\nreturn tx;};function tickTextObj(ax,x,text){var tf=ax.tickfont||{};return{x:x,dx:0,dy:0,text:text||'',fontSize:tf.size,font:tf.family,fontColor:tf.color};}function formatDate(ax,out,hover,extraPrecision){var tr=ax._tickround;var fmt=hover&&ax.hoverformat||axes.getTickFormat(ax);if(extraPrecision){// second or sub-second precision: extra always shows max digits.\n// for other fields, extra precision just adds one field.\nif(isNumeric(tr))tr=4;else tr={y:'m',m:'d',d:'M',M:'S',S:4}[tr];}var dateStr=Lib.formatDate(out.x,fmt,tr,ax._dateFormat,ax.calendar,ax._extraFormat);var headStr;var splitIndex=dateStr.indexOf('\\n');if(splitIndex!==-1){headStr=dateStr.substr(splitIndex+1);dateStr=dateStr.substr(0,splitIndex);}if(extraPrecision){// if extraPrecision led to trailing zeros, strip them off\n// actually, this can lead to removing even more zeros than\n// in the original rounding, but that's fine because in these\n// contexts uniformity is not so important (if there's even\n// anything to be uniform with!)\n// can we remove the whole time part?\nif(dateStr==='00:00:00'||dateStr==='00:00'){dateStr=headStr;headStr='';}else if(dateStr.length===8){// strip off seconds if they're zero (zero fractional seconds\n// are already omitted)\n// but we never remove minutes and leave just hours\ndateStr=dateStr.replace(/:00$/,'');}}if(headStr){if(hover){// hover puts it all on one line, so headPart works best up front\n// except for year headPart: turn this into \"Jan 1, 2000\" etc.\nif(tr==='d')dateStr+=', '+headStr;else dateStr=headStr+(dateStr?', '+dateStr:'');}else if(!ax._inCalcTicks||headStr!==ax._prevDateHead){dateStr+=' '+headStr;ax._prevDateHead=headStr;}}out.text=dateStr;}function formatLog(ax,out,hover,extraPrecision,hideexp){var dtick=ax.dtick;var x=out.x;var tickformat=ax.tickformat;var dtChar0=typeof dtick==='string'&&dtick.charAt(0);if(hideexp==='never'){// If this is a hover label, then we must *never* hide the exponent\n// for the sake of display, which could give the wrong value by\n// potentially many orders of magnitude. If hideexp was 'never', then\n// it's now succeeded by preventing the other condition from automating\n// this choice. Thus we can unset it so that the axis formatting takes\n// precedence.\nhideexp='';}if(extraPrecision&&dtChar0!=='L'){dtick='L3';dtChar0='L';}if(tickformat||dtChar0==='L'){out.text=numFormat(Math.pow(10,x),ax,hideexp,extraPrecision);}else if(isNumeric(dtick)||dtChar0==='D'&&Lib.mod(x+0.01,1)<0.1){var p=Math.round(x);var absP=Math.abs(p);var exponentFormat=ax.exponentformat;if(exponentFormat==='power'||isSIFormat(exponentFormat)&&beyondSI(p)){if(p===0)out.text=1;else if(p===1)out.text='10';else out.text='10'+(p>1?'':MINUS_SIGN)+absP+' ';out.fontSize*=1.25;}else if((exponentFormat==='e'||exponentFormat==='E')&&absP>2){out.text='1'+exponentFormat+(p>0?'+':MINUS_SIGN)+absP;}else{out.text=numFormat(Math.pow(10,x),ax,'','fakehover');if(dtick==='D1'&&ax._id.charAt(0)==='y'){out.dy-=out.fontSize/6;}}}else if(dtChar0==='D'){out.text=String(Math.round(Math.pow(10,Lib.mod(x,1))));out.fontSize*=0.75;}else throw'unrecognized dtick '+String(dtick);// if 9's are printed on log scale, move the 10's away a bit\nif(ax.dtick==='D1'){var firstChar=String(out.text).charAt(0);if(firstChar==='0'||firstChar==='1'){if(ax._id.charAt(0)==='y'){out.dx-=out.fontSize/4;}else{out.dy+=out.fontSize/2;out.dx+=(ax.range[1]>ax.range[0]?1:-1)*out.fontSize*(x<0?0.5:0.25);}}}}function formatCategory(ax,out){var tt=ax._categories[Math.round(out.x)];if(tt===undefined)tt='';out.text=String(tt);}function formatMultiCategory(ax,out,hover){var v=Math.round(out.x);var cats=ax._categories[v]||[];var tt=cats[1]===undefined?'':String(cats[1]);var tt2=cats[0]===undefined?'':String(cats[0]);if(hover){// TODO is this what we want?\nout.text=tt2+' - '+tt;}else{// setup for secondary labels\nout.text=tt;out.text2=tt2;}}function formatLinear(ax,out,hover,extraPrecision,hideexp){if(hideexp==='never'){// If this is a hover label, then we must *never* hide the exponent\n// for the sake of display, which could give the wrong value by\n// potentially many orders of magnitude. If hideexp was 'never', then\n// it's now succeeded by preventing the other condition from automating\n// this choice. Thus we can unset it so that the axis formatting takes\n// precedence.\nhideexp='';}else if(ax.showexponent==='all'&&Math.abs(out.x/ax.dtick)<1e-6){// don't add an exponent to zero if we're showing all exponents\n// so the only reason you'd show an exponent on zero is if it's the\n// ONLY tick to get an exponent (first or last)\nhideexp='hide';}out.text=numFormat(out.x,ax,hideexp,extraPrecision);}function formatAngle(ax,out,hover,extraPrecision,hideexp){if(ax.thetaunit==='radians'&&!hover){var num=out.x/180;if(num===0){out.text='0';}else{var frac=num2frac(num);if(frac[1]>=100){out.text=numFormat(Lib.deg2rad(out.x),ax,hideexp,extraPrecision);}else{var isNeg=out.x<0;if(frac[1]===1){if(frac[0]===1)out.text='π';else out.text=frac[0]+'π';}else{out.text=['',frac[0],' ','⁄','',frac[1],' ','π'].join('');}if(isNeg)out.text=MINUS_SIGN+out.text;}}}else{out.text=numFormat(out.x,ax,hideexp,extraPrecision);}}// inspired by\n// https://github.com/yisibl/num2fraction/blob/master/index.js\nfunction num2frac(num){function almostEq(a,b){return Math.abs(a-b)<=1e-6;}function findGCD(a,b){return almostEq(b,0)?a:findGCD(b,a%b);}function findPrecision(n){var e=1;while(!almostEq(Math.round(n*e)/e,n)){e*=10;}return e;}var precision=findPrecision(num);var number=num*precision;var gcd=Math.abs(findGCD(number,precision));return[// numerator\nMath.round(number/gcd),// denominator\nMath.round(precision/gcd)];}// format a number (tick value) according to the axis settings\n// new, more reliable procedure than d3.round or similar:\n// add half the rounding increment, then stringify and truncate\n// also automatically switch to sci. notation\nvar SIPREFIXES=['f','p','n','μ','m','','k','M','G','T'];function isSIFormat(exponentFormat){return exponentFormat==='SI'||exponentFormat==='B';}// are we beyond the range of common SI prefixes?\n// 10^-16 -> 1x10^-16\n// 10^-15 -> 1f\n// ...\n// 10^14 -> 100T\n// 10^15 -> 1x10^15\n// 10^16 -> 1x10^16\nfunction beyondSI(exponent){return exponent>14||exponent<-15;}function numFormat(v,ax,fmtoverride,hover){var isNeg=v<0;// max number of digits past decimal point to show\nvar tickRound=ax._tickround;var exponentFormat=fmtoverride||ax.exponentformat||'B';var exponent=ax._tickexponent;var tickformat=axes.getTickFormat(ax);var separatethousands=ax.separatethousands;// special case for hover: set exponent just for this value, and\n// add a couple more digits of precision over tick labels\nif(hover){// make a dummy axis obj to get the auto rounding and exponent\nvar ah={exponentformat:exponentFormat,dtick:ax.showexponent==='none'?ax.dtick:isNumeric(v)?Math.abs(v)||1:1,// if not showing any exponents, don't change the exponent\n// from what we calculate\nrange:ax.showexponent==='none'?ax.range.map(ax.r2d):[0,v||1]};autoTickRound(ah);tickRound=(Number(ah._tickround)||0)+4;exponent=ah._tickexponent;if(ax.hoverformat)tickformat=ax.hoverformat;}if(tickformat)return ax._numFormat(tickformat)(v).replace(/-/g,MINUS_SIGN);// 'epsilon' - rounding increment\nvar e=Math.pow(10,-tickRound)/2;// exponentFormat codes:\n// 'e' (1.2e+6, default)\n// 'E' (1.2E+6)\n// 'SI' (1.2M)\n// 'B' (same as SI except 10^9=B not G)\n// 'none' (1200000)\n// 'power' (1.2x10^6)\n// 'hide' (1.2, use 3rd argument=='hide' to eg\n// only show exponent on last tick)\nif(exponentFormat==='none')exponent=0;// take the sign out, put it back manually at the end\n// - makes cases easier\nv=Math.abs(v);if(v'+signedExponent+'';}else if(exponentFormat==='B'&&exponent===9){v+='B';}else if(isSIFormat(exponentFormat)){v+=SIPREFIXES[exponent/3+5];}}// put sign back in and return\n// replace standard minus character (which is technically a hyphen)\n// with a true minus sign\nif(isNeg)return MINUS_SIGN+v;return v;}axes.getTickFormat=function(ax){var i;function convertToMs(dtick){return typeof dtick!=='string'?dtick:Number(dtick.replace('M',''))*ONEAVGMONTH;}function compareLogTicks(left,right){var priority=['L','D'];if(typeof left===typeof right){if(typeof left==='number'){return left-right;}else{var leftPriority=priority.indexOf(left.charAt(0));var rightPriority=priority.indexOf(right.charAt(0));if(leftPriority===rightPriority){return Number(left.replace(/(L|D)/g,''))-Number(right.replace(/(L|D)/g,''));}else{return leftPriority-rightPriority;}}}else{return typeof left==='number'?1:-1;}}function isProperStop(dtick,range,convert){var convertFn=convert||function(x){return x;};var leftDtick=range[0];var rightDtick=range[1];return(!leftDtick&&typeof leftDtick!=='number'||convertFn(leftDtick)<=convertFn(dtick))&&(!rightDtick&&typeof rightDtick!=='number'||convertFn(rightDtick)>=convertFn(dtick));}function isProperLogStop(dtick,range){var isLeftDtickNull=range[0]===null;var isRightDtickNull=range[1]===null;var isDtickInRangeLeft=compareLogTicks(dtick,range[0])>=0;var isDtickInRangeRight=compareLogTicks(dtick,range[1])<=0;return(isLeftDtickNull||isDtickInRangeLeft)&&(isRightDtickNull||isDtickInRangeRight);}var tickstop,stopi;if(ax.tickformatstops&&ax.tickformatstops.length>0){switch(ax.type){case'date':case'linear':{for(i=0;i0?llbbox.bottom-pos:0,outsideTickLen);}}}if(ax.automargin){push={x:0,y:0,r:0,l:0,t:0,b:0};var domainIndices=[0,1];if(axLetter==='x'){if(s==='b'){push[s]=ax._depth;}else{push[s]=ax._depth=Math.max(llbbox.width>0?pos-llbbox.top:0,outsideTickLen);domainIndices.reverse();}if(llbbox.width>0){var rExtra=llbbox.right-(ax._offset+ax._length);if(rExtra>0){push.xr=1;push.r=rExtra;}var lExtra=ax._offset-llbbox.left;if(lExtra>0){push.xl=0;push.l=lExtra;}}}else{if(s==='l'){push[s]=ax._depth=Math.max(llbbox.height>0?pos-llbbox.left:0,outsideTickLen);}else{push[s]=ax._depth=Math.max(llbbox.height>0?llbbox.right-pos:0,outsideTickLen);domainIndices.reverse();}if(llbbox.height>0){var bExtra=llbbox.bottom-(ax._offset+ax._length);if(bExtra>0){push.yb=0;push.b=bExtra;}var tExtra=ax._offset-llbbox.top;if(tExtra>0){push.yt=1;push.t=tExtra;}}}push[counterLetter]=ax.anchor==='free'?ax.position:ax._anchorAxis.domain[domainIndices[0]];if(ax.title.text!==fullLayout._dfltTitle[axLetter]){push[s]+=approxTitleDepth(ax)+(ax.title.standoff||0);}if(ax.mirror&&ax.anchor!=='free'){mirrorPush={x:0,y:0,r:0,l:0,t:0,b:0};mirrorPush[sMirror]=ax.linewidth;if(ax.mirror&&ax.mirror!==true)mirrorPush[sMirror]+=outsideTickLen;if(ax.mirror===true||ax.mirror==='ticks'){mirrorPush[counterLetter]=ax._anchorAxis.domain[domainIndices[1]];}else if(ax.mirror==='all'||ax.mirror==='allticks'){mirrorPush[counterLetter]=[ax._counterDomainMin,ax._counterDomainMax][domainIndices[1]];}}}if(hasRangeSlider){rangeSliderPush=Registry.getComponentMethod('rangeslider','autoMarginOpts')(gd,ax);}Plots.autoMargin(gd,axAutoMarginID(ax),push);Plots.autoMargin(gd,axMirrorAutoMarginID(ax),mirrorPush);Plots.autoMargin(gd,rangeSliderAutoMarginID(ax),rangeSliderPush);});if(!opts.skipTitle&&!(hasRangeSlider&&ax.side==='bottom')){seq.push(function(){return drawTitle(gd,ax);});}return Lib.syncOrAsync(seq);};function getBoundaryVals(ax,vals){var out=[];var i;// boundaryVals are never used for labels;\n// no need to worry about the other tickTextObj keys\nvar _push=function(d,bndIndex){var xb=d.xbnd[bndIndex];if(xb!==null){out.push(Lib.extendFlat({},d,{x:xb}));}};if(vals.length){for(i=0;i, to make Drawing.bBox\n// retrieve a bbox computed with transform info\n//\n// To improve perf, it would be nice to use `thisLabel.node()`\n// (like in fixLabelOverlaps) instead and use Axes.getPxPosition\n// together with the makeLabelFns outputs and `tickangle`\n// to compute one bbox per (tick value x tick style)\nvar bb=Drawing.bBox(thisLabel.node().parentNode);top=Math.min(top,bb.top);bottom=Math.max(bottom,bb.bottom);left=Math.min(left,bb.left);right=Math.max(right,bb.right);});}else{top=0;bottom=0;left=0;right=0;}return{top:top,bottom:bottom,left:left,right:right,height:bottom-top,width:right-left};}/**\n * Which direction do the 'ax.side' values, and free ticks go?\n *\n * @param {object} ax (full) axis object\n * - {string} _id (starting with 'x' or 'y')\n * - {string} side\n * - {string} ticks\n * @return {array} all entries are either -1 or 1\n * - [0]: sign for top/right ticks (i.e. negative SVG direction)\n * - [1]: sign for bottom/left ticks (i.e. positive SVG direction)\n * - [2]: sign for ticks corresponding to 'ax.side'\n * - [3]: sign for ticks mirroring 'ax.side'\n * - [4]: sign of arrow starting at axis pointing towards margin\n */axes.getTickSigns=function(ax){var axLetter=ax._id.charAt(0);var sideOpposite={x:'top',y:'right'}[axLetter];var main=ax.side===sideOpposite?1:-1;var out=[-1,1,main,-main];// then we flip if outside XOR y axis\nif(ax.ticks!=='inside'===(axLetter==='x')){out=out.map(function(v){return-v;});}// independent of `ticks`; do not flip this one\nif(ax.side){out.push({l:-1,t:-1,r:1,b:1}[ax.side.charAt(0)]);}return out;};/**\n * Make axis translate transform function\n *\n * @param {object} ax (full) axis object\n * - {string} _id\n * - {number} _offset\n * - {fn} l2p\n * @return {fn} function of calcTicks items\n */axes.makeTransFn=function(ax){var axLetter=ax._id.charAt(0);var offset=ax._offset;return axLetter==='x'?function(d){return'translate('+(offset+ax.l2p(d.x))+',0)';}:function(d){return'translate(0,'+(offset+ax.l2p(d.x))+')';};};/**\n * Make axis tick path string\n *\n * @param {object} ax (full) axis object\n * - {string} _id\n * - {number} ticklen\n * - {number} linewidth\n * @param {number} shift along direction of ticklen\n * @param {1 or -1} sgn tick sign\n * @param {number (optional)} len tick length\n * @return {string}\n */axes.makeTickPath=function(ax,shift,sgn,len){len=len!==undefined?len:ax.ticklen;var axLetter=ax._id.charAt(0);var pad=(ax.linewidth||1)/2;return axLetter==='x'?'M0,'+(shift+pad*sgn)+'v'+len*sgn:'M'+(shift+pad*sgn)+',0h'+len*sgn;};/**\n * Make axis tick label x, y and anchor functions\n *\n * @param {object} ax (full) axis object\n * - {string} _id\n * - {string} ticks\n * - {number} ticklen\n * - {string} side\n * - {number} linewidth\n * - {number} tickfont.size\n * - {boolean} showline\n * @param {number} shift\n * @param {number} angle [in degrees] ...\n * @return {object}\n * - {fn} xFn\n * - {fn} yFn\n * - {fn} anchorFn\n * - {fn} heightFn\n * - {number} labelStandoff (gap parallel to ticks)\n * - {number} labelShift (gap perpendicular to ticks)\n */axes.makeLabelFns=function(ax,shift,angle){var axLetter=ax._id.charAt(0);var ticksOnOutsideLabels=ax.tickson!=='boundaries'&&ax.ticks==='outside';var labelStandoff=0;var labelShift=0;if(ticksOnOutsideLabels){labelStandoff+=ax.ticklen;}if(angle&&ax.ticks==='outside'){var rad=Lib.deg2rad(angle);labelStandoff=ax.ticklen*Math.cos(rad)+1;labelShift=ax.ticklen*Math.sin(rad);}if(ax.showticklabels&&(ticksOnOutsideLabels||ax.showline)){labelStandoff+=0.2*ax.tickfont.size;}labelStandoff+=(ax.linewidth||1)/2;var out={labelStandoff:labelStandoff,labelShift:labelShift};var x0,y0,ff,flipIt;if(axLetter==='x'){flipIt=ax.side==='bottom'?1:-1;x0=labelShift*flipIt;y0=shift+labelStandoff*flipIt;ff=ax.side==='bottom'?1:-0.2;out.xFn=function(d){return d.dx+x0;};out.yFn=function(d){return d.dy+y0+d.fontSize*ff;};out.anchorFn=function(d,a){if(!isNumeric(a)||a===0||a===180){return'middle';}return a*flipIt<0?'end':'start';};out.heightFn=function(d,a,h){return a<-60||a>60?-0.5*h:ax.side==='top'?-h:0;};}else if(axLetter==='y'){flipIt=ax.side==='right'?1:-1;x0=labelStandoff;y0=-labelShift*flipIt;ff=Math.abs(ax.tickangle)===90?0.5:0;out.xFn=function(d){return d.dx+shift+(x0+d.fontSize*ff)*flipIt;};out.yFn=function(d){return d.dy+y0+d.fontSize*MID_SHIFT;};out.anchorFn=function(d,a){if(isNumeric(a)&&Math.abs(a)===90){return'middle';}return ax.side==='right'?'start':'end';};out.heightFn=function(d,a,h){a*=ax.side==='left'?1:-1;return a<-30?-h:a<30?-0.5*h:0;};}return out;};function tickDataFn(d){return[d.text,d.x,d.axInfo,d.font,d.fontSize,d.fontColor].join('_');}/**\n * Draw axis ticks\n *\n * @param {DOM element} gd\n * @param {object} ax (full) axis object\n * - {string} _id\n * - {string} ticks\n * - {number} linewidth\n * - {string} tickcolor\n * @param {object} opts\n * - {array of object} vals (calcTicks output-like)\n * - {d3 selection} layer\n * - {string or fn} path\n * - {fn} transFn\n * - {boolean} crisp (set to false to unset crisp-edge SVG rendering)\n */axes.drawTicks=function(gd,ax,opts){opts=opts||{};var cls=ax._id+'tick';var ticks=opts.layer.selectAll('path.'+cls).data(ax.ticks?opts.vals:[],tickDataFn);ticks.exit().remove();ticks.enter().append('path').classed(cls,1).classed('ticks',1).classed('crisp',opts.crisp!==false).call(Color.stroke,ax.tickcolor).style('stroke-width',Drawing.crispRound(gd,ax.tickwidth,1)+'px').attr('d',opts.path);ticks.attr('transform',opts.transFn);};/**\n * Draw axis grid\n *\n * @param {DOM element} gd\n * @param {object} ax (full) axis object\n * - {string} _id\n * - {boolean} showgrid\n * - {string} gridcolor\n * - {string} gridwidth\n * - {boolean} zeroline\n * - {string} type\n * - {string} dtick\n * @param {object} opts\n * - {array of object} vals (calcTicks output-like)\n * - {d3 selection} layer\n * - {object} counterAxis (full axis object corresponding to counter axis)\n * optional - only required if this axis supports zero lines\n * - {string or fn} path\n * - {fn} transFn\n * - {boolean} crisp (set to false to unset crisp-edge SVG rendering)\n */axes.drawGrid=function(gd,ax,opts){opts=opts||{};var cls=ax._id+'grid';var vals=opts.vals;var counterAx=opts.counterAxis;if(ax.showgrid===false){vals=[];}else if(counterAx&&axes.shouldShowZeroLine(gd,ax,counterAx)){var isArrayMode=ax.tickmode==='array';for(var i=0;i1&&p1){for(j=1;jncnt*2;}// are the (x,y)-values in gd.data mostly text?\n// require twice as many DISTINCT categories as distinct numbers\nfunction category(a){// test at most 1000 points\nvar inc=Math.max(1,(a.length-1)/1000);var curvenums=0;var curvecats=0;var seen={};for(var i=0;icurvenums*2;}// very-loose requirements for multicategory,\n// trace modules that should never auto-type to multicategory\n// should be declared with 'noMultiCategory'\nfunction multiCategory(a){return Lib.isArrayOrTypedArray(a[0])&&Lib.isArrayOrTypedArray(a[1]);}},{\"../../constants/numerical\":711,\"../../lib\":735,\"fast-isnumeric\":237}],785:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var isNumeric=_dereq_('fast-isnumeric');var Registry=_dereq_('../../registry');var Lib=_dereq_('../../lib');var handleArrayContainerDefaults=_dereq_('../array_container_defaults');var layoutAttributes=_dereq_('./layout_attributes');var handleTickValueDefaults=_dereq_('./tick_value_defaults');var handleTickMarkDefaults=_dereq_('./tick_mark_defaults');var handleTickLabelDefaults=_dereq_('./tick_label_defaults');var handleCategoryOrderDefaults=_dereq_('./category_order_defaults');var handleLineGridDefaults=_dereq_('./line_grid_defaults');var setConvert=_dereq_('./set_convert');var DAY_OF_WEEK=_dereq_('./constants').WEEKDAY_PATTERN;var HOUR=_dereq_('./constants').HOUR_PATTERN;/**\n * options: object containing:\n *\n * letter: 'x' or 'y'\n * title: name of the axis (ie 'Colorbar') to go in default title\n * font: the default font to inherit\n * outerTicks: boolean, should ticks default to outside?\n * showGrid: boolean, should gridlines be shown by default?\n * noHover: boolean, this axis doesn't support hover effects?\n * noTickson: boolean, this axis doesn't support 'tickson'\n * data: the plot data, used to manage categories\n * bgColor: the plot background color, to calculate default gridline colors\n * calendar:\n * splomStash:\n * visibleDflt: boolean\n * reverseDflt: boolean\n * automargin: boolean\n */module.exports=function handleAxisDefaults(containerIn,containerOut,coerce,options,layoutOut){var letter=options.letter;var font=options.font||{};var splomStash=options.splomStash||{};var visible=coerce('visible',!options.visibleDflt);var axTemplate=containerOut._template||{};var axType=containerOut.type||axTemplate.type||'-';if(axType==='date'){var handleCalendarDefaults=Registry.getComponentMethod('calendars','handleDefaults');handleCalendarDefaults(containerIn,containerOut,'calendar',options.calendar);}setConvert(containerOut,layoutOut);var autorangeDflt=!containerOut.isValidRange(containerIn.range);if(autorangeDflt&&options.reverseDflt)autorangeDflt='reversed';var autoRange=coerce('autorange',autorangeDflt);if(autoRange&&(axType==='linear'||axType==='-'))coerce('rangemode');coerce('range');containerOut.cleanRange();handleCategoryOrderDefaults(containerIn,containerOut,coerce,options);if(axType!=='category'&&!options.noHover)coerce('hoverformat');var dfltColor=coerce('color');// if axis.color was provided, use it for fonts too; otherwise,\n// inherit from global font color in case that was provided.\n// Compare to dflt rather than to containerIn, so we can provide color via\n// template too.\nvar dfltFontColor=dfltColor!==layoutAttributes.color.dflt?dfltColor:font.color;// try to get default title from splom trace, fallback to graph-wide value\nvar dfltTitle=splomStash.label||layoutOut._dfltTitle[letter];handleTickLabelDefaults(containerIn,containerOut,coerce,axType,options,{pass:1});if(!visible)return containerOut;coerce('title.text',dfltTitle);Lib.coerceFont(coerce,'title.font',{family:font.family,size:Math.round(font.size*1.2),color:dfltFontColor});handleTickValueDefaults(containerIn,containerOut,coerce,axType);handleTickLabelDefaults(containerIn,containerOut,coerce,axType,options,{pass:2});handleTickMarkDefaults(containerIn,containerOut,coerce,options);handleLineGridDefaults(containerIn,containerOut,coerce,{dfltColor:dfltColor,bgColor:options.bgColor,showGrid:options.showGrid,attributes:layoutAttributes});if(containerOut.showline||containerOut.ticks)coerce('mirror');if(options.automargin)coerce('automargin');var isMultiCategory=axType==='multicategory';if(!options.noTickson&&(axType==='category'||isMultiCategory)&&(containerOut.ticks||containerOut.showgrid)){var ticksonDflt;if(isMultiCategory)ticksonDflt='boundaries';coerce('tickson',ticksonDflt);}if(isMultiCategory){var showDividers=coerce('showdividers');if(showDividers){coerce('dividercolor');coerce('dividerwidth');}}if(axType==='date'){handleArrayContainerDefaults(containerIn,containerOut,{name:'rangebreaks',inclusionAttr:'enabled',handleItemDefaults:rangebreaksDefaults});if(!containerOut.rangebreaks.length){delete containerOut.rangebreaks;}else{for(var k=0;k=2){var dfltPattern='';var i,q;if(bnds.length===2){for(i=0;i<2;i++){q=indexOfDay(bnds[i]);if(q){dfltPattern=DAY_OF_WEEK;break;}}}var pattern=coerce('pattern',dfltPattern);if(pattern===DAY_OF_WEEK){for(i=0;i<2;i++){q=indexOfDay(bnds[i]);if(q){// convert to integers i.e 'Sunday' --> 0\nitemOut.bounds[i]=bnds[i]=q-1;}}}if(pattern){// ensure types and ranges\nfor(i=0;i<2;i++){q=bnds[i];switch(pattern){case DAY_OF_WEEK:if(!isNumeric(q)){itemOut.enabled=false;return;}q=+q;if(q!==Math.floor(q)||// don't accept fractional days for mow\nq<0||q>=7){itemOut.enabled=false;return;}// use number\nitemOut.bounds[i]=bnds[i]=q;break;case HOUR:if(!isNumeric(q)){itemOut.enabled=false;return;}q=+q;if(q<0||q>24){// accept 24\nitemOut.enabled=false;return;}// use number\nitemOut.bounds[i]=bnds[i]=q;break;}}}if(containerOut.autorange===false){var rng=containerOut.range;// if bounds are bigger than the (set) range, disable break\nif(rng[0]rng[1]){itemOut.enabled=false;return;}}else if(bnds[0]>rng[0]&&bnds[1]letter2?1:-1;return+(id1.substr(1)||1)-+(id2.substr(1)||1);};exports.getAxisGroup=function getAxisGroup(fullLayout,axId){var matchGroups=fullLayout._axisMatchGroups;for(var i=0;i0;// override default 'categoryorder' value when non-empty array is supplied\nvar orderDefault;if(isValidArray)orderDefault='array';var order=coerce('categoryorder',orderDefault);var array;// coerce 'categoryarray' only in array order case\nif(order==='array'){array=coerce('categoryarray');}// cannot set 'categoryorder' to 'array' with an invalid 'categoryarray'\nif(!isValidArray&&order==='array'){order=containerOut.categoryorder='trace';}// set up things for makeCalcdata\nif(order==='trace'){containerOut._initialCategories=[];}else if(order==='array'){containerOut._initialCategories=array.slice();}else{array=findCategories(containerOut,opts).sort();if(order==='category ascending'){containerOut._initialCategories=array;}else if(order==='category descending'){containerOut._initialCategories=array.reverse();}}};},{}],788:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var isNumeric=_dereq_('fast-isnumeric');var Lib=_dereq_('../../lib');var ONEDAY=_dereq_('../../constants/numerical').ONEDAY;/**\n * Return a validated dtick value for this axis\n *\n * @param {any} dtick: the candidate dtick. valid values are numbers and strings,\n * and further constrained depending on the axis type.\n * @param {string} axType: the axis type\n */exports.dtick=function(dtick,axType){var isLog=axType==='log';var isDate=axType==='date';var isCat=axType==='category';var dtickDflt=isDate?ONEDAY:1;if(!dtick)return dtickDflt;if(isNumeric(dtick)){dtick=Number(dtick);if(dtick<=0)return dtickDflt;if(isCat){// category dtick must be positive integers\nreturn Math.max(1,Math.round(dtick));}if(isDate){// date dtick must be at least 0.1ms (our current precision)\nreturn Math.max(0.1,dtick);}return dtick;}if(typeof dtick!=='string'||!(isDate||isLog)){return dtickDflt;}var prefix=dtick.charAt(0);var dtickNum=dtick.substr(1);dtickNum=isNumeric(dtickNum)?Number(dtickNum):0;if(dtickNum<=0||!(// \"M\" gives ticks every (integer) n months\nisDate&&prefix==='M'&&dtickNum===Math.round(dtickNum)||// \"L\" gives ticks linearly spaced in data (not in position) every (float) f\nisLog&&prefix==='L'||// \"D1\" gives powers of 10 with all small digits between, \"D2\" gives only 2 and 5\nisLog&&prefix==='D'&&(dtickNum===1||dtickNum===2))){return dtickDflt;}return dtick;};/**\n * Return a validated tick0 for this axis\n *\n * @param {any} tick0: the candidate tick0. Valid values are numbers and strings,\n * further constrained depending on the axis type\n * @param {string} axType: the axis type\n * @param {string} calendar: for date axes, the calendar to validate/convert with\n * @param {any} dtick: an already valid dtick. Only used for D1 and D2 log dticks,\n * which do not support tick0 at all.\n */exports.tick0=function(tick0,axType,calendar,dtick){if(axType==='date'){return Lib.cleanDate(tick0,Lib.dateTick0(calendar));}if(dtick==='D1'||dtick==='D2'){// D1 and D2 modes ignore tick0 entirely\nreturn undefined;}// Aside from date axes, tick0 must be numeric\nreturn isNumeric(tick0)?Number(tick0):0;};},{\"../../constants/numerical\":711,\"../../lib\":735,\"fast-isnumeric\":237}],789:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var counterRegex=_dereq_('../../lib/regex').counter;module.exports={idRegex:{x:counterRegex('x'),y:counterRegex('y')},attrRegex:counterRegex('[xy]axis'),// axis match regular expression\nxAxisMatch:counterRegex('xaxis'),yAxisMatch:counterRegex('yaxis'),// pattern matching axis ids and names\n// note that this is more permissive than counterRegex, as\n// id2name, name2id, and cleanId accept \"x1\" etc\nAX_ID_PATTERN:/^[xyz][0-9]*$/,AX_NAME_PATTERN:/^[xyz]axis[0-9]*$/,// and for 2D subplots\nSUBPLOT_PATTERN:/^x([0-9]*)y([0-9]*)$/,HOUR_PATTERN:'hour',WEEKDAY_PATTERN:'day of week',// pixels to move mouse before you stop clamping to starting point\nMINDRAG:8,// smallest dimension allowed for a select box\nMINSELECT:12,// smallest dimension allowed for a zoombox\nMINZOOM:20,// width of axis drag regions\nDRAGGERSIZE:20,// max pixels off straight before a lasso select line counts as bent\nBENDPX:1.5,// delay before a redraw (relayout) after smooth panning and zooming\nREDRAWDELAY:50,// throttling limit (ms) for selectPoints calls\nSELECTDELAY:100,// cache ID suffix for throttle\nSELECTID:'-select',// last resort axis ranges for x and y axes if we have no data\nDFLTRANGEX:[-1,6],DFLTRANGEY:[-1,4],// Layers to keep trace types in the right order\n// N.B. each 'unique' plot method must have its own layer\ntraceLayerClasses:['imagelayer','heatmaplayer','contourcarpetlayer','contourlayer','funnellayer','waterfalllayer','barlayer','carpetlayer','violinlayer','boxlayer','ohlclayer','scattercarpetlayer','scatterlayer'],clipOnAxisFalseQuery:['.scatterlayer','.barlayer','.funnellayer','.waterfalllayer'],layerValue2layerClass:{'above traces':'above','below traces':'below'}};},{\"../../lib/regex\":751}],790:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Lib=_dereq_('../../lib');var id2name=_dereq_('./axis_ids').id2name;var scaleZoom=_dereq_('./scale_zoom');var makePadFn=_dereq_('./autorange').makePadFn;var concatExtremes=_dereq_('./autorange').concatExtremes;var ALMOST_EQUAL=_dereq_('../../constants/numerical').ALMOST_EQUAL;var FROM_BL=_dereq_('../../constants/alignment').FROM_BL;exports.handleConstraintDefaults=function(containerIn,containerOut,coerce,opts){var allAxisIds=opts.allAxisIds;var layoutOut=opts.layoutOut;var scaleanchorDflt=opts.scaleanchorDflt;var constrainDflt=opts.constrainDflt;var constraintGroups=layoutOut._axisConstraintGroups;var matchGroups=layoutOut._axisMatchGroups;var axId=containerOut._id;var axLetter=axId.charAt(0);var splomStash=((layoutOut._splomAxes||{})[axLetter]||{})[axId]||{};var thisID=containerOut._id;var letter=thisID.charAt(0);// coerce the constraint mechanics even if this axis has no scaleanchor\n// because it may be the anchor of another axis.\nvar constrain=coerce('constrain',constrainDflt);Lib.coerce(containerIn,containerOut,{constraintoward:{valType:'enumerated',values:letter==='x'?['left','center','right']:['bottom','middle','top'],dflt:letter==='x'?'center':'middle'}},'constraintoward');var matches,matchOpts;if((containerIn.matches||splomStash.matches)&&!containerOut.fixedrange){matchOpts=getConstraintOpts(matchGroups,thisID,allAxisIds,layoutOut);matches=Lib.coerce(containerIn,containerOut,{matches:{valType:'enumerated',values:matchOpts.linkableAxes||[],dflt:splomStash.matches}},'matches');}// 'matches' wins over 'scaleanchor' (for now)\nvar scaleanchor,scaleOpts;if(!matches&&!(containerOut.fixedrange&&constrain!=='domain')&&(containerIn.scaleanchor||scaleanchorDflt)){scaleOpts=getConstraintOpts(constraintGroups,thisID,allAxisIds,layoutOut,constrain);scaleanchor=Lib.coerce(containerIn,containerOut,{scaleanchor:{valType:'enumerated',values:scaleOpts.linkableAxes||[]}},'scaleanchor',scaleanchorDflt);}if(matches){delete containerOut.constrain;updateConstraintGroups(matchGroups,matchOpts.thisGroup,thisID,matches,1);}else if(allAxisIds.indexOf(containerIn.matches)!==-1){Lib.warn('ignored '+containerOut._name+'.matches: \"'+containerIn.matches+'\" to avoid either an infinite loop '+'or because the target axis has fixed range.');}if(scaleanchor){var scaleratio=coerce('scaleratio');// TODO: I suppose I could do attribute.min: Number.MIN_VALUE to avoid zero,\n// but that seems hacky. Better way to say \"must be a positive number\"?\n// Of course if you use several super-tiny values you could eventually\n// force a product of these to zero and all hell would break loose...\n// Likewise with super-huge values.\nif(!scaleratio)scaleratio=containerOut.scaleratio=1;updateConstraintGroups(constraintGroups,scaleOpts.thisGroup,thisID,scaleanchor,scaleratio);}else if(allAxisIds.indexOf(containerIn.scaleanchor)!==-1){Lib.warn('ignored '+containerOut._name+'.scaleanchor: \"'+containerIn.scaleanchor+'\" to avoid either an infinite loop '+'and possibly inconsistent scaleratios, or because the target '+'axis has fixed range or this axis declares a *matches* constraint.');}};// If this axis is already part of a constraint group, we can't\n// scaleanchor any other axis in that group, or we'd make a loop.\n// Filter allAxisIds to enforce this, also matching axis types.\nfunction getConstraintOpts(groups,thisID,allAxisIds,layoutOut,constrain){var doesNotConstrainRange=constrain!=='range';var thisType=layoutOut[id2name(thisID)].type;var i,j,idj,axj;var linkableAxes=[];for(j=0;jALMOST_EQUAL*maxScale&&!hasAnyDomainConstraint)continue;// now increase any ranges we need to until all normalized scales are equal\nfor(j=0;jouterMin&&newValrangeMax){rangeMax=newVal;}}var domainExpand=(rangeMax-rangeMin)/(2*halfRange);factor/=domainExpand;rangeMin=ax.l2r(rangeMin);rangeMax=ax.l2r(rangeMax);ax.range=ax._input.range=rl0=0){gd._fullLayout._deactivateShape(gd);return;}var clickmode=gd._fullLayout.clickmode;removeZoombox(gd);if(numClicks===2&&!singleEnd)doubleClick();if(isMainDrag){if(clickmode.indexOf('select')>-1){selectOnClick(evt,gd,xaxes,yaxes,plotinfo.id,dragOptions);}if(clickmode.indexOf('event')>-1){Fx.click(gd,evt,plotinfo.id);}}else if(numClicks===1&&singleEnd){var ax=ns?ya0:xa0;var end=ns==='s'||ew==='w'?0:1;var attrStr=ax._name+'.range['+end+']';var initialText=getEndText(ax,end);var hAlign='left';var vAlign='middle';if(ax.fixedrange)return;if(ns){vAlign=ns==='n'?'top':'bottom';if(ax.side==='right')hAlign='right';}else if(ew==='e')hAlign='right';if(gd._context.showAxisRangeEntryBoxes){d3.select(dragger).call(svgTextUtils.makeEditable,{gd:gd,immediate:true,background:gd._fullLayout.paper_bgcolor,text:String(initialText),fill:ax.tickfont?ax.tickfont.color:'#444',horizontalAlign:hAlign,verticalAlign:vAlign}).on('edit',function(text){var v=ax.d2r(text);if(v!==undefined){Registry.call('_guiRelayout',gd,attrStr,v);}});}}}dragElement.init(dragOptions);// x/y px position at start of drag\nvar x0,y0;// bbox object of the zoombox\nvar box;// luminance of bg behind zoombox\nvar lum;// zoombox path outline\nvar path0;// is zoombox dimmed (during drag)\nvar dimmed;// 'x'-only, 'y' or 'xy' zooming\nvar zoomMode;// zoombox d3 selection\nvar zb;// zoombox corner d3 selection\nvar corners;// zoom takes over minDrag, so it also has to take over gd._dragged\nvar zoomDragged;function zoomPrep(e,startX,startY){var dragBBox=dragger.getBoundingClientRect();x0=startX-dragBBox.left;y0=startY-dragBBox.top;box={l:x0,r:x0,w:0,t:y0,b:y0,h:0};lum=gd._hmpixcount?gd._hmlumcount/gd._hmpixcount:tinycolor(gd._fullLayout.plot_bgcolor).getLuminance();path0='M0,0H'+pw+'V'+ph+'H0V0';dimmed=false;zoomMode='xy';zoomDragged=false;zb=makeZoombox(zoomlayer,lum,xs,ys,path0);corners=makeCorners(zoomlayer,xs,ys);}function zoomMove(dx0,dy0){if(gd._transitioningWithDuration){return false;}var x1=Math.max(0,Math.min(pw,dx0+x0));var y1=Math.max(0,Math.min(ph,dy0+y0));var dx=Math.abs(x1-x0);var dy=Math.abs(y1-y0);box.l=Math.min(x0,x1);box.r=Math.max(x0,x1);box.t=Math.min(y0,y1);box.b=Math.max(y0,y1);function noZoom(){zoomMode='';box.r=box.l;box.t=box.b;corners.attr('d','M0,0Z');}if(links.isSubplotConstrained){if(dx>MINZOOM||dy>MINZOOM){zoomMode='xy';if(dx/pw>dy/ph){dy=dx*ph/pw;if(y0>y1)box.t=y0-dy;else box.b=y0+dy;}else{dx=dy*pw/ph;if(x0>x1)box.l=x0-dx;else box.r=x0+dx;}corners.attr('d',xyCorners(box));}else{noZoom();}}else if(matches.isSubplotConstrained){if(dx>MINZOOM||dy>MINZOOM){zoomMode='xy';var r0=Math.min(box.l/pw,(ph-box.b)/ph);var r1=Math.max(box.r/pw,(ph-box.t)/ph);box.l=r0*pw;box.r=r1*pw;box.b=(1-r0)*ph;box.t=(1-r1)*ph;corners.attr('d',xyCorners(box));}else{noZoom();}}else if(!yActive||dy0 is compressing scale (cursor is over the plot,\n// the axis end should move with the cursor)\n// d<0 is expanding (cursor is off the plot, axis end moves\n// nonlinearly so you can expand far)\nfunction dZoom(d){return 1-(d>=0?Math.min(d,0.9):1/(1/Math.max(d,-0.3)+3.222));}function getDragCursor(nsew,dragmode,isMainDrag){if(!nsew)return'pointer';if(nsew==='nsew'){// in this case here, clear cursor and\n// use the cursor style set on \nif(isMainDrag)return'';if(dragmode==='pan')return'move';return'crosshair';}return nsew.toLowerCase()+'-resize';}function makeZoombox(zoomlayer,lum,xs,ys,path0){return zoomlayer.append('path').attr('class','zoombox').style({'fill':lum>0.2?'rgba(0,0,0,0)':'rgba(255,255,255,0)','stroke-width':0}).attr('transform','translate('+xs+', '+ys+')').attr('d',path0+'Z');}function makeCorners(zoomlayer,xs,ys){return zoomlayer.append('path').attr('class','zoombox-corners').style({fill:Color.background,stroke:Color.defaultLine,'stroke-width':1,opacity:0}).attr('transform','translate('+xs+', '+ys+')').attr('d','M0,0Z');}function updateZoombox(zb,corners,box,path0,dimmed,lum){zb.attr('d',path0+'M'+box.l+','+box.t+'v'+box.h+'h'+box.w+'v-'+box.h+'h-'+box.w+'Z');transitionZoombox(zb,corners,dimmed,lum);}function transitionZoombox(zb,corners,dimmed,lum){if(!dimmed){zb.transition().style('fill',lum>0.2?'rgba(0,0,0,0.4)':'rgba(255,255,255,0.3)').duration(200);corners.transition().style('opacity',1).duration(200);}}function removeZoombox(gd){d3.select(gd).selectAll('.zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners').remove();}function showDoubleClickNotifier(gd){if(SHOWZOOMOUTTIP&&gd.data&&gd._context.showTips){Lib.notifier(Lib._(gd,'Double-click to zoom back out'),'long');SHOWZOOMOUTTIP=false;}}function xCorners(box,y0){return'M'+(box.l-0.5)+','+(y0-MINZOOM-0.5)+'h-3v'+(2*MINZOOM+1)+'h3ZM'+(box.r+0.5)+','+(y0-MINZOOM-0.5)+'h3v'+(2*MINZOOM+1)+'h-3Z';}function yCorners(box,x0){return'M'+(x0-MINZOOM-0.5)+','+(box.t-0.5)+'v-3h'+(2*MINZOOM+1)+'v3ZM'+(x0-MINZOOM-0.5)+','+(box.b+0.5)+'v3h'+(2*MINZOOM+1)+'v-3Z';}function xyCorners(box){var clen=Math.floor(Math.min(box.b-box.t,box.r-box.l,MINZOOM)/2);return'M'+(box.l-3.5)+','+(box.t-0.5+clen)+'h3v'+-clen+'h'+clen+'v-3h-'+(clen+3)+'ZM'+(box.r+3.5)+','+(box.t-0.5+clen)+'h-3v'+-clen+'h'+-clen+'v-3h'+(clen+3)+'ZM'+(box.r+3.5)+','+(box.b+0.5-clen)+'h-3v'+clen+'h'+-clen+'v3h'+(clen+3)+'ZM'+(box.l-3.5)+','+(box.b+0.5-clen)+'h3v'+clen+'h'+clen+'v3h-'+(clen+3)+'Z';}function calcLinks(gd,groups,xaHash,yaHash){var isSubplotConstrained=false;var xLinks={};var yLinks={};var xID,yID,xLinkID,yLinkID;for(var i=0;i cursor style.\n//\n// Note that changing the axis configuration and/or the fixedrange attribute\n// should trigger a full initInteractions.\nexports.updateFx=function(gd){var fullLayout=gd._fullLayout;var cursor=fullLayout.dragmode==='pan'?'move':'crosshair';setCursor(fullLayout._draggers,cursor);};},{\"../../components/dragelement\":621,\"../../components/fx\":642,\"../../lib/setcursor\":755,\"./constants\":789,\"./dragbox\":791,\"d3\":165}],793:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';function clearOutlineControllers(gd){var zoomLayer=gd._fullLayout._zoomlayer;if(zoomLayer){zoomLayer.selectAll('.outline-controllers').remove();}}function clearSelect(gd){var zoomLayer=gd._fullLayout._zoomlayer;if(zoomLayer){// until we get around to persistent selections, remove the outline\n// here. The selection itself will be removed when the plot redraws\n// at the end.\nzoomLayer.selectAll('.select-outline').remove();}gd._fullLayout._drawing=false;}module.exports={clearOutlineControllers:clearOutlineControllers,clearSelect:clearSelect};},{}],794:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';// in v2 (once log ranges are fixed),\n// we'll be able to p2r here for all axis types\nfunction p2r(ax,v){switch(ax.type){case'log':return ax.p2d(v);case'date':return ax.p2r(v,0,ax.calendar);default:return ax.p2r(v);}}function r2p(ax,v){switch(ax.type){case'log':return ax.d2p(v);case'date':return ax.r2p(v,0,ax.calendar);default:return ax.r2p(v);}}function axValue(ax){var index=ax._id.charAt(0)==='y'?1:0;return function(v){return p2r(ax,v[index]);};}function getTransform(plotinfo){return'translate('+plotinfo.xaxis._offset+','+plotinfo.yaxis._offset+')';}module.exports={p2r:p2r,r2p:r2p,axValue:axValue,getTransform:getTransform};},{}],795:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Registry=_dereq_('../../registry');var Lib=_dereq_('../../lib');/**\n * Factory function for checking component arrays for subplot references.\n *\n * @param {string} containerArrayName: the top-level array in gd.layout to check\n * If an item in this container is found that references a cartesian x and/or y axis,\n * ensure cartesian is marked as a base plot module and record the axes (and subplot\n * if both refs are axes) in gd._fullLayout\n *\n * @return {function}: with args layoutIn (gd.layout) and layoutOut (gd._fullLayout)\n * as expected of a component includeBasePlot method\n */module.exports=function makeIncludeComponents(containerArrayName){return function includeComponents(layoutIn,layoutOut){var array=layoutIn[containerArrayName];if(!Array.isArray(array))return;var Cartesian=Registry.subplotsRegistry.cartesian;var idRegex=Cartesian.idRegex;var subplots=layoutOut._subplots;var xaList=subplots.xaxis;var yaList=subplots.yaxis;var cartesianList=subplots.cartesian;var hasCartesianOrGL2D=layoutOut._has('cartesian')||layoutOut._has('gl2d');for(var i=0;i so that the new cartesian subplot\n// can have the correct layer ordering\nif(oldFullLayout._hasOnlyLargeSploms&&!newFullLayout._hasOnlyLargeSploms){for(k in oldPlots){plotinfo=oldPlots[k];if(plotinfo.plotgroup)plotinfo.plotgroup.remove();}}var hadGl=oldFullLayout._has&&oldFullLayout._has('gl');var hasGl=newFullLayout._has&&newFullLayout._has('gl');if(hadGl&&!hasGl){for(k in oldPlots){plotinfo=oldPlots[k];if(plotinfo._scene)plotinfo._scene.destroy();}}// delete any titles we don't need anymore\n// check if axis list has changed, and if so clear old titles\nif(oldSubplotList.xaxis&&oldSubplotList.yaxis){var oldAxIDs=axisIds.listIds({_fullLayout:oldFullLayout});for(i=0;is here\n// as other subplots may need them\n});// must remove overlaid subplot trace layers 'manually'\nfor(var k in fullLayout._plots){var subplotInfo=fullLayout._plots[k];var overlays=subplotInfo.overlays||[];for(var j=0;jdomain[1]-1/4096)containerOut.domain=dfltDomain;Lib.noneOrAll(containerIn.domain,containerOut.domain,dfltDomain);}coerce('layer');return containerOut;};},{\"../../lib\":735,\"fast-isnumeric\":237}],801:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var FROM_BL=_dereq_('../../constants/alignment').FROM_BL;module.exports=function scaleZoom(ax,factor,centerFraction){if(centerFraction===undefined){centerFraction=FROM_BL[ax.constraintoward||'center'];}var rangeLinear=[ax.r2l(ax.range[0]),ax.r2l(ax.range[1])];var center=rangeLinear[0]+(rangeLinear[1]-rangeLinear[0])*centerFraction;ax.range=ax._input.range=[ax.l2r(center+(rangeLinear[0]-center)*factor),ax.l2r(center+(rangeLinear[1]-center)*factor)];};},{\"../../constants/alignment\":704}],802:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var polybool=_dereq_('polybooljs');var Registry=_dereq_('../../registry');var dashStyle=_dereq_('../../components/drawing').dashStyle;var Color=_dereq_('../../components/color');var Fx=_dereq_('../../components/fx');var makeEventData=_dereq_('../../components/fx/helpers').makeEventData;var dragHelpers=_dereq_('../../components/dragelement/helpers');var freeMode=dragHelpers.freeMode;var rectMode=dragHelpers.rectMode;var drawMode=dragHelpers.drawMode;var openMode=dragHelpers.openMode;var selectMode=dragHelpers.selectMode;var displayOutlines=_dereq_('../../components/shapes/draw_newshape/display_outlines');var handleEllipse=_dereq_('../../components/shapes/draw_newshape/helpers').handleEllipse;var newShapes=_dereq_('../../components/shapes/draw_newshape/newshapes');var Lib=_dereq_('../../lib');var polygon=_dereq_('../../lib/polygon');var throttle=_dereq_('../../lib/throttle');var getFromId=_dereq_('./axis_ids').getFromId;var clearGlCanvases=_dereq_('../../lib/clear_gl_canvases');var redrawReglTraces=_dereq_('../../plot_api/subroutines').redrawReglTraces;var constants=_dereq_('./constants');var MINSELECT=constants.MINSELECT;var filteredPolygon=polygon.filter;var polygonTester=polygon.tester;var clearSelect=_dereq_('./handle_outline').clearSelect;var helpers=_dereq_('./helpers');var p2r=helpers.p2r;var axValue=helpers.axValue;var getTransform=helpers.getTransform;function prepSelect(e,startX,startY,dragOptions,mode){var isFreeMode=freeMode(mode);var isRectMode=rectMode(mode);var isOpenMode=openMode(mode);var isDrawMode=drawMode(mode);var isSelectMode=selectMode(mode);var isLine=mode==='drawline';var isEllipse=mode==='drawcircle';var isLineOrEllipse=isLine||isEllipse;// cases with two start & end positions\nvar gd=dragOptions.gd;var fullLayout=gd._fullLayout;var zoomLayer=fullLayout._zoomlayer;var dragBBox=dragOptions.element.getBoundingClientRect();var plotinfo=dragOptions.plotinfo;var transform=getTransform(plotinfo);var x0=startX-dragBBox.left;var y0=startY-dragBBox.top;var x1=x0;var y1=y0;var path0='M'+x0+','+y0;var pw=dragOptions.xaxes[0]._length;var ph=dragOptions.yaxes[0]._length;var allAxes=dragOptions.xaxes.concat(dragOptions.yaxes);var subtract=e.altKey&&!(drawMode(mode)&&isOpenMode);var filterPoly,selectionTester,mergedPolygons,currentPolygon;var i,searchInfo,eventData;coerceSelectionsCache(e,gd,dragOptions);if(isFreeMode){filterPoly=filteredPolygon([[x0,y0]],constants.BENDPX);}var outlines=zoomLayer.selectAll('path.select-outline-'+plotinfo.id).data(isDrawMode?[0]:[1,2]);var drwStyle=fullLayout.newshape;outlines.enter().append('path').attr('class',function(d){return'select-outline select-outline-'+d+' select-outline-'+plotinfo.id;}).style(isDrawMode?{opacity:drwStyle.opacity/2,fill:isOpenMode?undefined:drwStyle.fillcolor,stroke:drwStyle.line.color,'stroke-dasharray':dashStyle(drwStyle.line.dash,drwStyle.line.width),'stroke-width':drwStyle.line.width+'px'}:{}).attr('fill-rule',drwStyle.fillrule).classed('cursor-move',isDrawMode?true:false).attr('transform',transform).attr('d',path0+'Z');var corners=zoomLayer.append('path').attr('class','zoombox-corners').style({fill:Color.background,stroke:Color.defaultLine,'stroke-width':1}).attr('transform',transform).attr('d','M0,0Z');var throttleID=fullLayout._uid+constants.SELECTID;var selection=[];// find the traces to search for selection points\nvar searchTraces=determineSearchTraces(gd,dragOptions.xaxes,dragOptions.yaxes,dragOptions.subplot);function ascending(a,b){return a-b;}// allow subplots to override fillRangeItems routine\nvar fillRangeItems;if(plotinfo.fillRangeItems){fillRangeItems=plotinfo.fillRangeItems;}else{if(isRectMode){fillRangeItems=function(eventData,poly){var ranges=eventData.range={};for(i=0;i=0){gd._fullLayout._deactivateShape(gd);return;}if(isDrawMode)return;var clickmode=fullLayout.clickmode;throttle.done(throttleID).then(function(){throttle.clear(throttleID);if(numClicks===2){// clear selection on doubleclick\noutlines.remove();for(i=0;i-1){selectOnClick(evt,gd,dragOptions.xaxes,dragOptions.yaxes,dragOptions.subplot,dragOptions,outlines);}if(clickmode==='event'){// TODO: remove in v2 - this was probably never intended to work as it does,\n// but in case anyone depends on it we don't want to break it now.\n// Note that click-to-select introduced pre v2 also emitts proper\n// event data when clickmode is having 'select' in its flag list.\ngd.emit('plotly_selected',undefined);}}Fx.click(gd,evt);}).catch(Lib.error);};dragOptions.doneFn=function(){corners.remove();throttle.done(throttleID).then(function(){throttle.clear(throttleID);dragOptions.gd.emit('plotly_selected',eventData);if(currentPolygon&&dragOptions.selectionDefs){// save last polygons\ncurrentPolygon.subtract=subtract;dragOptions.selectionDefs.push(currentPolygon);// we have to keep reference to arrays container\ndragOptions.mergedPolygons.length=0;[].push.apply(dragOptions.mergedPolygons,mergedPolygons);}if(dragOptions.doneFnCompleted){dragOptions.doneFnCompleted(selection);}}).catch(Lib.error);if(isDrawMode){clearSelectionsCache(dragOptions);}};}function selectOnClick(evt,gd,xAxes,yAxes,subplot,dragOptions,polygonOutlines){var hoverData=gd._hoverdata;var fullLayout=gd._fullLayout;var clickmode=fullLayout.clickmode;var sendEvents=clickmode.indexOf('event')>-1;var selection=[];var searchTraces,searchInfo,currentSelectionDef,selectionTester,traceSelection;var thisTracesSelection,pointOrBinSelected,subtract,eventData,i;if(isHoverDataSet(hoverData)){coerceSelectionsCache(evt,gd,dragOptions);searchTraces=determineSearchTraces(gd,xAxes,yAxes,subplot);var clickedPtInfo=extractClickedPtInfo(hoverData,searchTraces);var isBinnedTrace=clickedPtInfo.pointNumbers.length>0;// Note: potentially costly operation isPointOrBinSelected is\n// called as late as possible through the use of an assignment\n// in an if condition.\nif(isBinnedTrace?isOnlyThisBinSelected(searchTraces,clickedPtInfo):isOnlyOnePointSelected(searchTraces)&&(pointOrBinSelected=isPointOrBinSelected(clickedPtInfo))){if(polygonOutlines)polygonOutlines.remove();for(i=0;i=0){gd._fullLayout._deactivateShape(gd);}if(drawMode(dragmode)){var fullLayout=gd._fullLayout;var zoomLayer=fullLayout._zoomlayer;var outlines=zoomLayer.selectAll('.select-outline-'+plotinfo.id);if(outlines&&gd._fullLayout._drawing){// add shape\nvar shapes=newShapes(outlines,dragOptions);if(shapes){Registry.call('_guiRelayout',gd,{shapes:shapes});}gd._fullLayout._drawing=false;}}plotinfo.selection={};plotinfo.selection.selectionDefs=dragOptions.selectionDefs=[];plotinfo.selection.mergedPolygons=dragOptions.mergedPolygons=[];}function determineSearchTraces(gd,xAxes,yAxes,subplot){var searchTraces=[];var xAxisIds=xAxes.map(function(ax){return ax._id;});var yAxisIds=yAxes.map(function(ax){return ax._id;});var cd,trace,i;for(i=0;i0;// When pointsNumbers is set (e.g. histogram's binning),\n// it is assumed that when the first point of\n// a bin is selected, all others are as well\nvar ptNumToTest=ptNumsSet?ptNums[0]:ptNum;// TODO potential performance improvement\n// Primarily we need this function to determine if a click adds\n// or subtracts from a selection.\n// In cases `trace.selectedpoints` is a huge array, indexOf\n// might be slow. One remedy would be to introduce a hash somewhere.\nreturn trace.selectedpoints?trace.selectedpoints.indexOf(ptNumToTest)>-1:false;}function isOnlyThisBinSelected(searchTraces,clickedPtInfo){var tracesWithSelectedPts=[];var searchInfo,trace,isSameTrace,i;for(i=0;i0){tracesWithSelectedPts.push(searchInfo);}}if(tracesWithSelectedPts.length===1){isSameTrace=tracesWithSelectedPts[0]===clickedPtInfo.searchInfo;if(isSameTrace){trace=clickedPtInfo.searchInfo.cd[0].trace;if(trace.selectedpoints.length===clickedPtInfo.pointNumbers.length){for(i=0;i1)return false;len+=trace.selectedpoints.length;if(len>1)return false;}}return len===1;}function updateSelectedState(gd,searchTraces,eventData){var i,searchInfo,cd,trace;// before anything else, update preGUI if necessary\nfor(i=0;i0)return Math.log(v)/Math.LN10;else if(v<=0&&clip&&ax.range&&ax.range.length===2){// clip NaN (ie past negative infinity) to LOG_CLIP axis\n// length past the negative edge\nvar r0=ax.range[0];var r1=ax.range[1];return 0.5*(r0+r1-2*LOG_CLIP*Math.abs(r0-r1));}else return BADNUM;}/*\n * wrapped dateTime2ms that:\n * - accepts ms numbers for backward compatibility\n * - inserts a dummy arg so calendar is the 3rd arg (see notes below).\n * - defaults to ax.calendar\n */function dt2ms(v,_,calendar){// NOTE: Changed this behavior: previously we took any numeric value\n// to be a ms, even if it was a string that could be a bare year.\n// Now we convert it as a date if at all possible, and only try\n// as (local) ms if that fails.\nvar ms=dateTime2ms(v,calendar||ax.calendar);if(ms===BADNUM){if(isNumeric(v)){v=+v;// keep track of tenths of ms, that `new Date` will drop\n// same logic as in Lib.ms2DateTime\nvar msecTenths=Math.floor(Lib.mod(v+0.05,1)*10);var msRounded=Math.round(v-msecTenths/10);ms=dateTime2ms(new Date(msRounded))+msecTenths/10;}else return BADNUM;}return ms;}// wrapped ms2DateTime to insert default ax.calendar\nfunction ms2dt(v,r,calendar){return ms2DateTime(v,r,calendar||ax.calendar);}function getCategoryName(v){return ax._categories[Math.round(v)];}/*\n * setCategoryIndex: return the index of category v,\n * inserting it in the list if it's not already there\n *\n * this will enter the categories in the order it\n * encounters them, ie all the categories from the\n * first data set, then all the ones from the second\n * that aren't in the first etc.\n *\n * it is assumed that this function is being invoked in the\n * already sorted category order; otherwise there would be\n * a disconnect between the array and the index returned\n */function setCategoryIndex(v){if(isValidCategory(v)){if(ax._categoriesMap===undefined){ax._categoriesMap={};}if(ax._categoriesMap[v]!==undefined){return ax._categoriesMap[v];}else{ax._categories.push(typeof v==='number'?String(v):v);var curLength=ax._categories.length-1;ax._categoriesMap[v]=curLength;return curLength;}}return BADNUM;}function setMultiCategoryIndex(arrayIn,len){var arrayOut=new Array(len);for(var i=0;iax.range[1])flip=!flip;var signAx=flip?-1:1;var pos=signAx*v;var q=0;for(var i=0;imax)q=i+1;else{// when falls into break, pick 'closest' offset\nq=pos<(min+max)/2?i:i+1;break;}}var b2=ax._B[q]||0;if(!isFinite(b2))return 0;// avoid NaN translate e.g. in positionLabels if one keep zooming exactly into a break\nreturn _l2p(v,ax._m2,b2);};p2l=function(px){var len=ax._rangebreaks.length;if(!len)return _p2l(px,ax._m,ax._b);var q=0;for(var i=0;iax._rangebreaks[i].pmax)q=i+1;}return _p2l(px,ax._m2,ax._B[q]);};}// conversions among c/l/p are fairly simple - do them together for all axis types\nax.c2l=ax.type==='log'?toLog:ensureNumber;ax.l2c=ax.type==='log'?fromLog:ensureNumber;ax.l2p=l2p;ax.p2l=p2l;ax.c2p=ax.type==='log'?function(v,clip){return l2p(toLog(v,clip));}:l2p;ax.p2c=ax.type==='log'?function(px){return fromLog(p2l(px));}:p2l;/*\n * now type-specific conversions for **ALL** other combinations\n * they're all written out, instead of being combinations of each other, for\n * both clarity and speed.\n */if(['linear','-'].indexOf(ax.type)!==-1){// all are data vals, but d and r need cleaning\nax.d2r=ax.r2d=ax.d2c=ax.r2c=ax.d2l=ax.r2l=cleanNumber;ax.c2d=ax.c2r=ax.l2d=ax.l2r=ensureNumber;ax.d2p=ax.r2p=function(v){return ax.l2p(cleanNumber(v));};ax.p2d=ax.p2r=p2l;ax.cleanPos=ensureNumber;}else if(ax.type==='log'){// d and c are data vals, r and l are logged (but d and r need cleaning)\nax.d2r=ax.d2l=function(v,clip){return toLog(cleanNumber(v),clip);};ax.r2d=ax.r2c=function(v){return fromLog(cleanNumber(v));};ax.d2c=ax.r2l=cleanNumber;ax.c2d=ax.l2r=ensureNumber;ax.c2r=toLog;ax.l2d=fromLog;ax.d2p=function(v,clip){return ax.l2p(ax.d2r(v,clip));};ax.p2d=function(px){return fromLog(p2l(px));};ax.r2p=function(v){return ax.l2p(cleanNumber(v));};ax.p2r=p2l;ax.cleanPos=ensureNumber;}else if(ax.type==='date'){// r and d are date strings, l and c are ms\n/*\n * Any of these functions with r and d on either side, calendar is the\n * **3rd** argument. log has reserved the second argument.\n *\n * Unless you need the special behavior of the second arg (ms2DateTime\n * uses this to limit precision, toLog uses true to clip negatives\n * to offscreen low rather than undefined), it's safe to pass 0.\n */ax.d2r=ax.r2d=Lib.identity;ax.d2c=ax.r2c=ax.d2l=ax.r2l=dt2ms;ax.c2d=ax.c2r=ax.l2d=ax.l2r=ms2dt;ax.d2p=ax.r2p=function(v,_,calendar){return ax.l2p(dt2ms(v,0,calendar));};ax.p2d=ax.p2r=function(px,r,calendar){return ms2dt(p2l(px),r,calendar);};ax.cleanPos=function(v){return Lib.cleanDate(v,BADNUM,ax.calendar);};}else if(ax.type==='category'){// d is categories (string)\n// c and l are indices (numbers)\n// r is categories or numbers\nax.d2c=ax.d2l=setCategoryIndex;ax.r2d=ax.c2d=ax.l2d=getCategoryName;ax.d2r=ax.d2l_noadd=getCategoryPosition;ax.r2c=function(v){var index=getCategoryPosition(v);return index!==undefined?index:ax.fraction2r(0.5);};ax.l2r=ax.c2r=ensureNumber;ax.r2l=getCategoryPosition;ax.d2p=function(v){return ax.l2p(ax.r2c(v));};ax.p2d=function(px){return getCategoryName(p2l(px));};ax.r2p=ax.d2p;ax.p2r=p2l;ax.cleanPos=function(v){if(typeof v==='string'&&v!=='')return v;return ensureNumber(v);};}else if(ax.type==='multicategory'){// N.B. multicategory axes don't define d2c and d2l,\n// as 'data-to-calcdata' conversion needs to take into\n// account all data array items as in ax.makeCalcdata.\nax.r2d=ax.c2d=ax.l2d=getCategoryName;ax.d2r=ax.d2l_noadd=getCategoryPosition;ax.r2c=function(v){var index=getCategoryPosition(v);return index!==undefined?index:ax.fraction2r(0.5);};ax.r2c_just_indices=getCategoryIndex;ax.l2r=ax.c2r=ensureNumber;ax.r2l=getCategoryPosition;ax.d2p=function(v){return ax.l2p(ax.r2c(v));};ax.p2d=function(px){return getCategoryName(p2l(px));};ax.r2p=ax.d2p;ax.p2r=p2l;ax.cleanPos=function(v){if(Array.isArray(v)||typeof v==='string'&&v!=='')return v;return ensureNumber(v);};ax.setupMultiCategory=function(fullData){var traceIndices=ax._traceIndices;var i,j;var matchGroups=fullLayout._axisMatchGroups;if(matchGroups&&matchGroups.length&&ax._categories.length===0){for(i=0;iFP_SAFE)range[i]=FP_SAFE;if(range[0]===range[1]){// somewhat arbitrary: split by 1 or 1ppm, whichever is bigger\nvar inc=Math.max(1,Math.abs(range[0]*1e-6));range[0]-=inc;range[1]+=inc;}}}};// set scaling to pixels\nax.setScale=function(usePrivateRange){var gs=fullLayout._size;// make sure we have a domain (pull it in from the axis\n// this one is overlaying if necessary)\nif(ax.overlaying){var ax2=axisIds.getFromId({_fullLayout:fullLayout},ax.overlaying);ax.domain=ax2.domain;}// While transitions are occurring, we get a double-transform\n// issue if we transform the drawn layer *and* use the new axis range to\n// draw the data. This allows us to construct setConvert using the pre-\n// interaction values of the range:\nvar rangeAttr=usePrivateRange&&ax._r?'_r':'range';var calendar=ax.calendar;ax.cleanRange(rangeAttr);var rl0=ax.r2l(ax[rangeAttr][0],calendar);var rl1=ax.r2l(ax[rangeAttr][1],calendar);var isY=axLetter==='y';if(isY){ax._offset=gs.t+(1-ax.domain[1])*gs.h;ax._length=gs.h*(ax.domain[1]-ax.domain[0]);ax._m=ax._length/(rl0-rl1);ax._b=-ax._m*rl1;}else{ax._offset=gs.l+ax.domain[0]*gs.w;ax._length=gs.w*(ax.domain[1]-ax.domain[0]);ax._m=ax._length/(rl1-rl0);ax._b=-ax._m*rl0;}// set of \"N\" disjoint rangebreaks inside the range\nax._rangebreaks=[];// length of these rangebreaks in value space - negative on reversed axes\nax._lBreaks=0;// l2p slope (same for all intervals)\nax._m2=0;// set of l2p offsets (one for each of the (N+1) piecewise intervals)\nax._B=[];if(ax.rangebreaks){var i,brk;ax._rangebreaks=ax.locateBreaks(Math.min(rl0,rl1),Math.max(rl0,rl1));if(ax._rangebreaks.length){for(i=0;irl1)flip=!flip;if(flip)ax._rangebreaks.reverse();var sign=flip?-1:1;ax._m2=sign*ax._length/(Math.abs(rl1-rl0)-ax._lBreaks);ax._B.push(-ax._m2*(isY?rl1:rl0));for(i=0;ib1){b1+=7;if(vbb1){b1+=24;if(vb=b0&&vb=b0&&vbrkj.max||maxbrkj.max){brkj.max=max;}isNewBreak=false;}}if(isNewBreak){rangebreaksOut.push({min:min,max:max});}};for(i=0;i rect').call(Drawing.setTranslate,0,0).call(Drawing.setScale,1,1);subplot.plot.call(Drawing.setTranslate,xa._offset,ya._offset).call(Drawing.setScale,1,1);var traceGroups=subplot.plot.selectAll('.scatterlayer .trace');// This is specifically directed at scatter traces, applying an inverse\n// scale to individual points to counteract the scale of the trace\n// as a whole:\ntraceGroups.selectAll('.point').call(Drawing.setPointGroupScale,1,1);traceGroups.selectAll('.textpoint').call(Drawing.setTextPointsScale,1,1);traceGroups.call(Drawing.hideOutsideRangePoints,subplot);}function updateSubplot(edit,progress){var plotinfo=edit.plotinfo;var xa=plotinfo.xaxis;var ya=plotinfo.yaxis;var xlen=xa._length;var ylen=ya._length;var editX=!!edit.xr1;var editY=!!edit.yr1;var viewBox=[];if(editX){var xr0=Lib.simpleMap(edit.xr0,xa.r2l);var xr1=Lib.simpleMap(edit.xr1,xa.r2l);var dx0=xr0[1]-xr0[0];var dx1=xr1[1]-xr1[0];viewBox[0]=(xr0[0]*(1-progress)+progress*xr1[0]-xr0[0])/(xr0[1]-xr0[0])*xlen;viewBox[2]=xlen*(1-progress+progress*dx1/dx0);xa.range[0]=xa.l2r(xr0[0]*(1-progress)+progress*xr1[0]);xa.range[1]=xa.l2r(xr0[1]*(1-progress)+progress*xr1[1]);}else{viewBox[0]=0;viewBox[2]=xlen;}if(editY){var yr0=Lib.simpleMap(edit.yr0,ya.r2l);var yr1=Lib.simpleMap(edit.yr1,ya.r2l);var dy0=yr0[1]-yr0[0];var dy1=yr1[1]-yr1[0];viewBox[1]=(yr0[1]*(1-progress)+progress*yr1[1]-yr0[1])/(yr0[0]-yr0[1])*ylen;viewBox[3]=ylen*(1-progress+progress*dy1/dy0);ya.range[0]=xa.l2r(yr0[0]*(1-progress)+progress*yr1[0]);ya.range[1]=ya.l2r(yr0[1]*(1-progress)+progress*yr1[1]);}else{viewBox[1]=0;viewBox[3]=ylen;}Axes.drawOne(gd,xa,{skipTitle:true});Axes.drawOne(gd,ya,{skipTitle:true});Axes.redrawComponents(gd,[xa._id,ya._id]);var xScaleFactor=editX?xlen/viewBox[2]:1;var yScaleFactor=editY?ylen/viewBox[3]:1;var clipDx=editX?viewBox[0]:0;var clipDy=editY?viewBox[1]:0;var fracDx=editX?viewBox[0]/viewBox[2]*xlen:0;var fracDy=editY?viewBox[1]/viewBox[3]*ylen:0;var plotDx=xa._offset-fracDx;var plotDy=ya._offset-fracDy;plotinfo.clipRect.call(Drawing.setTranslate,clipDx,clipDy).call(Drawing.setScale,1/xScaleFactor,1/yScaleFactor);plotinfo.plot.call(Drawing.setTranslate,plotDx,plotDy).call(Drawing.setScale,xScaleFactor,yScaleFactor);// apply an inverse scale to individual points to counteract\n// the scale of the trace group.\nDrawing.setPointGroupScale(plotinfo.zoomScalePts,1/xScaleFactor,1/yScaleFactor);Drawing.setTextPointsScale(plotinfo.zoomScaleTxt,1/xScaleFactor,1/yScaleFactor);}var onComplete;if(makeOnCompleteCallback){// This module makes the choice whether or not it notifies Plotly.transition\n// about completion:\nonComplete=makeOnCompleteCallback();}function transitionComplete(){var aobj={};for(var i=0;itransitionOpts.duration){transitionComplete();raf=window.cancelAnimationFrame(doFrame);}else{raf=window.requestAnimationFrame(doFrame);}}t1=Date.now();raf=window.requestAnimationFrame(doFrame);return Promise.resolve();};},{\"../../components/drawing\":624,\"../../lib\":735,\"../../registry\":866,\"./axes\":783,\"d3\":165}],808:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var traceIs=_dereq_('../../registry').traceIs;var autoType=_dereq_('./axis_autotype');/*\n * data: the plot data to use in choosing auto type\n * name: axis object name (ie 'xaxis') if one should be stored\n */module.exports=function handleTypeDefaults(containerIn,containerOut,coerce,options){var axType=coerce('type',(options.splomStash||{}).type);if(axType==='-'){setAutoType(containerOut,options.data);if(containerOut.type==='-'){containerOut.type='linear';}else{// copy autoType back to input axis\n// note that if this object didn't exist\n// in the input layout, we have to put it in\n// this happens in the main supplyDefaults function\ncontainerIn.type=containerOut.type;}}};function setAutoType(ax,data){// new logic: let people specify any type they want,\n// only autotype if type is '-'\nif(ax.type!=='-')return;var id=ax._id;var axLetter=id.charAt(0);var i;// support 3d\nif(id.indexOf('scene')!==-1)id=axLetter;var d0=getFirstNonEmptyTrace(data,id,axLetter);if(!d0)return;// first check for histograms, as the count direction\n// should always default to a linear axis\nif(d0.type==='histogram'&&axLetter==={v:'y',h:'x'}[d0.orientation||'v']){ax.type='linear';return;}var calAttr=axLetter+'calendar';var calendar=d0[calAttr];var opts={noMultiCategory:!traceIs(d0,'cartesian')||traceIs(d0,'noMultiCategory')};// To not confuse 2D x/y used for per-box sample points for multicategory coordinates\nif(d0.type==='box'&&d0._hasPreCompStats&&axLetter==={h:'x',v:'y'}[d0.orientation||'v']){opts.noMultiCategory=true;}// check all boxes on this x axis to see\n// if they're dates, numbers, or categories\nif(isBoxWithoutPositionCoords(d0,axLetter)){var posLetter=getBoxPosLetter(d0);var boxPositions=[];for(i=0;i0&&(trace['_'+axLetter+'axes']||{})[id]){return trace;}if((trace[axLetter+'axis']||axLetter)===id){if(isBoxWithoutPositionCoords(trace,axLetter)){return trace;}else if((trace[axLetter]||[]).length||trace[axLetter+'0']){return trace;}}}}function getBoxPosLetter(trace){return{v:'x',h:'y'}[trace.orientation||'v'];}function isBoxWithoutPositionCoords(trace,axLetter){var posLetter=getBoxPosLetter(trace);var isBox=traceIs(trace,'box-violin');var isCandlestick=traceIs(trace._fullInput||{},'candlestick');return isBox&&!isCandlestick&&axLetter===posLetter&&trace[posLetter]===undefined&&trace[posLetter+'0']===undefined;}},{\"../../registry\":866,\"./axis_autotype\":784}],809:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Registry=_dereq_('../registry');var Lib=_dereq_('../lib');/*\n * Create or update an observer. This function is designed to be\n * idempotent so that it can be called over and over as the component\n * updates, and will attach and detach listeners as needed.\n *\n * @param {optional object} container\n * An object on which the observer is stored. This is the mechanism\n * by which it is idempotent. If it already exists, another won't be\n * added. Each time it's called, the value lookup table is updated.\n * @param {array} commandList\n * An array of commands, following either `buttons` of `updatemenus`\n * or `steps` of `sliders`.\n * @param {function} onchange\n * A listener called when the value is changed. Receives data object\n * with information about the new state.\n */exports.manageCommandObserver=function(gd,container,commandList,onchange){var ret={};var enabled=true;if(container&&container._commandObserver){ret=container._commandObserver;}if(!ret.cache){ret.cache={};}// Either create or just recompute this:\nret.lookupTable={};var binding=exports.hasSimpleAPICommandBindings(gd,commandList,ret.lookupTable);if(container&&container._commandObserver){if(!binding){// If container exists and there are no longer any bindings,\n// remove existing:\nif(container._commandObserver.remove){container._commandObserver.remove();container._commandObserver=null;return ret;}}else{// If container exists and there *are* bindings, then the lookup\n// table should have been updated and check is already attached,\n// so there's nothing to be done:\nreturn ret;}}// Determine whether there's anything to do for this binding:\nif(binding){// Build the cache:\nbindingValueHasChanged(gd,binding,ret.cache);ret.check=function check(){if(!enabled)return;var update=bindingValueHasChanged(gd,binding,ret.cache);if(update.changed&&onchange){// Disable checks for the duration of this command in order to avoid\n// infinite loops:\nif(ret.lookupTable[update.value]!==undefined){ret.disable();Promise.resolve(onchange({value:update.value,type:binding.type,prop:binding.prop,traces:binding.traces,index:ret.lookupTable[update.value]})).then(ret.enable,ret.enable);}}return update.changed;};var checkEvents=['plotly_relayout','plotly_redraw','plotly_restyle','plotly_update','plotly_animatingframe','plotly_afterplot'];for(var i=0;i0?'.':'')+attrName;if(Lib.isPlainObject(attr)){crawl(attr,callback,thisPath,depth+1);}else{// Only execute the callback on leaf nodes:\ncallback(thisPath,attrName,attr);}});}},{\"../lib\":735,\"../registry\":866}],810:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var extendFlat=_dereq_('../lib/extend').extendFlat;/**\n * Make a xy domain attribute group\n *\n * @param {object} opts\n * @param {string}\n * opts.name: name to be inserted in the default description\n * @param {boolean}\n * opts.trace: set to true for trace containers\n * @param {string}\n * opts.editType: editType for all pieces\n * @param {boolean}\n * opts.noGridCell: set to true to omit `row` and `column`\n *\n * @param {object} extra\n * @param {string}\n * extra.description: extra description. N.B we use\n * a separate extra container to make it compatible with\n * the compress_attributes transform.\n *\n * @return {object} attributes object containing {x,y} as specified\n */exports.attributes=function(opts,extra){opts=opts||{};extra=extra||{};var base={valType:'info_array',editType:opts.editType,items:[{valType:'number',min:0,max:1,editType:opts.editType},{valType:'number',min:0,max:1,editType:opts.editType}],dflt:[0,1]};var namePart=opts.name?opts.name+' ':'';var contPart=opts.trace?'trace ':'subplot ';var descPart=extra.description?' '+extra.description:'';var out={x:extendFlat({},base,{}),y:extendFlat({},base,{}),editType:opts.editType};if(!opts.noGridCell){out.row={valType:'integer',min:0,dflt:0,editType:opts.editType};out.column={valType:'integer',min:0,dflt:0,editType:opts.editType};}return out;};exports.defaults=function(containerOut,layout,coerce,dfltDomains){var dfltX=dfltDomains&&dfltDomains.x||[0,1];var dfltY=dfltDomains&&dfltDomains.y||[0,1];var grid=layout.grid;if(grid){var column=coerce('domain.column');if(column!==undefined){if(column0){trace._module.calcGeoJSON(calcTrace,fullLayout);}}var hasInvalidBounds=this.updateProjection(geoCalcData,fullLayout);if(hasInvalidBounds)return;if(!this.viewInitial||this.scope!==geoLayout.scope){this.saveViewInitial(geoLayout);}this.scope=geoLayout.scope;this.updateBaseLayers(fullLayout,geoLayout);this.updateDims(fullLayout,geoLayout);this.updateFx(fullLayout,geoLayout);Plots.generalUpdatePerTraceModule(this.graphDiv,this,geoCalcData,geoLayout);var scatterLayer=this.layers.frontplot.select('.scatterlayer');this.dataPoints.point=scatterLayer.selectAll('.point');this.dataPoints.text=scatterLayer.selectAll('text');this.dataPaths.line=scatterLayer.selectAll('.js-line');var choroplethLayer=this.layers.backplot.select('.choroplethlayer');this.dataPaths.choropleth=choroplethLayer.selectAll('path');this.render();};proto.updateProjection=function(geoCalcData,fullLayout){var gd=this.graphDiv;var geoLayout=fullLayout[this.id];var gs=fullLayout._size;var domain=geoLayout.domain;var projLayout=geoLayout.projection;var lonaxis=geoLayout.lonaxis;var lataxis=geoLayout.lataxis;var axLon=lonaxis._ax;var axLat=lataxis._ax;var projection=this.projection=getProjection(geoLayout);// setup subplot extent [[x0,y0], [x1,y1]]\nvar extent=[[gs.l+gs.w*domain.x[0],gs.t+gs.h*(1-domain.y[1])],[gs.l+gs.w*domain.x[1],gs.t+gs.h*(1-domain.y[0])]];var center=geoLayout.center||{};var rotation=projLayout.rotation||{};var lonaxisRange=lonaxis.range||[];var lataxisRange=lataxis.range||[];if(geoLayout.fitbounds){axLon._length=extent[1][0]-extent[0][0];axLat._length=extent[1][1]-extent[0][1];axLon.range=getAutoRange(gd,axLon);axLat.range=getAutoRange(gd,axLat);var midLon=(axLon.range[0]+axLon.range[1])/2;var midLat=(axLat.range[0]+axLat.range[1])/2;if(geoLayout._isScoped){center={lon:midLon,lat:midLat};}else if(geoLayout._isClipped){center={lon:midLon,lat:midLat};rotation={lon:midLon,lat:midLat,roll:rotation.roll};var projType=projLayout.type;var lonHalfSpan=constants.lonaxisSpan[projType]/2||180;var latHalfSpan=constants.lataxisSpan[projType]/2||180;lonaxisRange=[midLon-lonHalfSpan,midLon+lonHalfSpan];lataxisRange=[midLat-latHalfSpan,midLat+latHalfSpan];}else{center={lon:midLon,lat:midLat};rotation={lon:midLon,lat:rotation.lat,roll:rotation.roll};}}// set 'pre-fit' projection\nprojection.center([center.lon-rotation.lon,center.lat-rotation.lat]).rotate([-rotation.lon,-rotation.lat,rotation.roll]).parallels(projLayout.parallels);// fit projection 'scale' and 'translate' to set lon/lat ranges\nvar rangeBox=makeRangeBox(lonaxisRange,lataxisRange);projection.fitExtent(extent,rangeBox);var b=this.bounds=projection.getBounds(rangeBox);var s=this.fitScale=projection.scale();var t=projection.translate();if(!isFinite(b[0][0])||!isFinite(b[0][1])||!isFinite(b[1][0])||!isFinite(b[1][1])||isNaN(t[0])||isNaN(t[0])){var attrToUnset=['fitbounds','projection.rotation','center','lonaxis.range','lataxis.range'];var msg='Invalid geo settings, relayout\\'ing to default view.';var updateObj={};// clear all attributes that could cause invalid bounds,\n// clear viewInitial to update reset-view behavior\nfor(var i=0;i-1){selectOnClick(d3.event,gd,[_this.xaxis],[_this.yaxis],_this.id,dragOptions);}if(clickMode.indexOf('event')>-1){// TODO: like pie and mapbox, this doesn't support right-click\n// actually this one is worse, as right-click starts a pan, or leaves\n// select in a weird state.\n// Also, only tangentially related, we should cancel hover during pan\nFx.click(gd,d3.event);}}});};proto.makeFramework=function(){var _this=this;var gd=_this.graphDiv;var fullLayout=gd._fullLayout;var clipId='clip'+fullLayout._uid+_this.id;_this.clipDef=fullLayout._clips.append('clipPath').attr('id',clipId);_this.clipRect=_this.clipDef.append('rect');_this.framework=d3.select(_this.container).append('g').attr('class','geo '+_this.id).call(Drawing.setClipUrl,clipId,gd);// sane lonlat to px\n_this.project=function(v){var px=_this.projection(v);return px?[px[0]-_this.xaxis._offset,px[1]-_this.yaxis._offset]:[null,null];};_this.xaxis={_id:'x',c2p:function(v){return _this.project(v)[0];}};_this.yaxis={_id:'y',c2p:function(v){return _this.project(v)[1];}};// mock axis for hover formatting\n_this.mockAxis={type:'linear',showexponent:'all',exponentformat:'B'};Axes.setConvert(_this.mockAxis,fullLayout);};proto.saveViewInitial=function(geoLayout){var center=geoLayout.center||{};var projLayout=geoLayout.projection;var rotation=projLayout.rotation||{};this.viewInitial={'fitbounds':geoLayout.fitbounds,'projection.scale':projLayout.scale};var extra;if(geoLayout._isScoped){extra={'center.lon':center.lon,'center.lat':center.lat};}else if(geoLayout._isClipped){extra={'projection.rotation.lon':rotation.lon,'projection.rotation.lat':rotation.lat};}else{extra={'center.lon':center.lon,'center.lat':center.lat,'projection.rotation.lon':rotation.lon};}Lib.extendFlat(this.viewInitial,extra);};// [hot code path] (re)draw all paths which depend on the projection\nproto.render=function(){var projection=this.projection;var pathFn=projection.getPath();var k;function translatePoints(d){var lonlatPx=projection(d.lonlat);return lonlatPx?'translate('+lonlatPx[0]+','+lonlatPx[1]+')':null;}function hideShowPoints(d){return projection.isLonLatOverEdges(d.lonlat)?'none':null;}for(k in this.basePaths){this.basePaths[k].attr('d',pathFn);}for(k in this.dataPaths){this.dataPaths[k].attr('d',function(d){return pathFn(d.geojson);});}for(k in this.dataPoints){this.dataPoints[k].attr('display',hideShowPoints).attr('transform',translatePoints);}};// Helper that wraps d3.geo[/* projection name /*]() which:\n//\n// - adds 'fitExtent' (available in d3 v4)\n// - adds 'getPath', 'getBounds' convenience methods\n// - scopes logic related to 'clipAngle'\n// - adds 'isLonLatOverEdges' method\n// - sets projection precision\n// - sets methods that aren't always defined depending\n// on the projection type to a dummy 'd3-esque' function,\n//\n// This wrapper alleviates subsequent code of (many) annoying if-statements.\nfunction getProjection(geoLayout){var projLayout=geoLayout.projection;var projType=projLayout.type;var projection=d3.geo[constants.projNames[projType]]();var clipAngle=geoLayout._isClipped?constants.lonaxisSpan[projType]/2:null;var methods=['center','rotate','parallels','clipExtent'];var dummyFn=function(_){return _?projection:[];};for(var i=0;imaxAngle;}else{return false;}};projection.getPath=function(){return d3.geo.path().projection(projection);};projection.getBounds=function(object){return projection.getPath().bounds(object);};// adapted from d3 v4:\n// https://github.com/d3/d3-geo/blob/master/src/projection/fit.js\nprojection.fitExtent=function(extent,object){var w=extent[1][0]-extent[0][0];var h=extent[1][1]-extent[0][1];var clip=projection.clipExtent&&projection.clipExtent();projection.scale(150).translate([0,0]);if(clip)projection.clipExtent(null);var b=projection.getBounds(object);var k=Math.min(w/(b[1][0]-b[0][0]),h/(b[1][1]-b[0][1]));var x=+extent[0][0]+(w-k*(b[1][0]+b[0][0]))/2;var y=+extent[0][1]+(h-k*(b[1][1]+b[0][1]))/2;if(clip)projection.clipExtent(clip);return projection.scale(k*150).translate([x,y]);};projection.precision(constants.precision);if(clipAngle){projection.clipAngle(clipAngle-constants.clipPad);}return projection;}function makeGraticule(axisName,geoLayout,fullLayout){// equivalent to the d3 \"ε\"\nvar epsilon=1e-6;// same as the geoGraticule default\nvar precision=2.5;var axLayout=geoLayout[axisName];var scopeDefaults=constants.scopeDefaults[geoLayout.scope];var rng;var oppRng;var coordFn;if(axisName==='lonaxis'){rng=scopeDefaults.lonaxisRange;oppRng=scopeDefaults.lataxisRange;coordFn=function(v,l){return[v,l];};}else if(axisName==='lataxis'){rng=scopeDefaults.lataxisRange;oppRng=scopeDefaults.lonaxisRange;coordFn=function(v,l){return[l,v];};}var dummyAx={type:'linear',range:[rng[0],rng[1]-epsilon],tick0:axLayout.tick0,dtick:axLayout.dtick};Axes.setConvert(dummyAx,fullLayout);var vals=Axes.calcTicks(dummyAx);// remove duplicate on antimeridian\nif(!geoLayout.isScoped&&axisName==='lonaxis'){vals.pop();}var len=vals.length;var coords=new Array(len);for(var i=0;i0&&lon1<0)lon1+=360;var dlon4=(lon1-lon0)/4;return{type:'Polygon',coordinates:[[[lon0,lat0],[lon0,lat1],[lon0+dlon4,lat1],[lon0+2*dlon4,lat1],[lon0+3*dlon4,lat1],[lon1,lat1],[lon1,lat0],[lon1-dlon4,lat0],[lon1-2*dlon4,lat0],[lon1-3*dlon4,lat0],[lon0,lat0]]]};}},{\"../../components/color\":602,\"../../components/dragelement\":621,\"../../components/drawing\":624,\"../../components/fx\":642,\"../../lib\":735,\"../../lib/geo_location_utils\":729,\"../../lib/topojson_utils\":762,\"../../registry\":866,\"../cartesian/autorange\":782,\"../cartesian/axes\":783,\"../cartesian/select\":802,\"../plots\":846,\"./constants\":813,\"./projections\":818,\"./zoom\":819,\"d3\":165,\"topojson-client\":538}],815:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var getSubplotCalcData=_dereq_('../../plots/get_data').getSubplotCalcData;var counterRegex=_dereq_('../../lib').counterRegex;var createGeo=_dereq_('./geo');var GEO='geo';var counter=counterRegex(GEO);var attributes={};attributes[GEO]={valType:'subplotid',dflt:GEO,editType:'calc'};function plotGeo(gd){var fullLayout=gd._fullLayout;var calcData=gd.calcdata;var geoIds=fullLayout._subplots[GEO];for(var i=0;i0&&lon1<0)lon1+=360;var centerLon=(lon0+lon1)/2;var projLon;if(!isAlbersUsa){var dfltProjRotate=isScoped?scopeParams.projRotate:[centerLon,0,0];projLon=coerce('projection.rotation.lon',dfltProjRotate[0]);coerce('projection.rotation.lat',dfltProjRotate[1]);coerce('projection.rotation.roll',dfltProjRotate[2]);show=coerce('showcoastlines',!isScoped&&visible);if(show){coerce('coastlinecolor');coerce('coastlinewidth');}show=coerce('showocean',!visible?false:undefined);if(show)coerce('oceancolor');}var centerLonDflt;var centerLatDflt;if(isAlbersUsa){// 'albers usa' does not have a 'center',\n// these values were found using via:\n// projection.invert([geoLayout.center.lon, geoLayoutIn.center.lat])\ncenterLonDflt=-96.6;centerLatDflt=38.7;}else{centerLonDflt=isScoped?centerLon:projLon;centerLatDflt=(latRange[0]+latRange[1])/2;}coerce('center.lon',centerLonDflt);coerce('center.lat',centerLatDflt);if(isConic){var dfltProjParallels=scopeParams.projParallels||[0,60];coerce('projection.parallels',dfltProjParallels);}coerce('projection.scale');show=coerce('showland',!visible?false:undefined);if(show)coerce('landcolor');show=coerce('showlakes',!visible?false:undefined);if(show)coerce('lakecolor');show=coerce('showrivers',!visible?false:undefined);if(show){coerce('rivercolor');coerce('riverwidth');}show=coerce('showcountries',isScoped&&scope!=='usa'&&visible);if(show){coerce('countrycolor');coerce('countrywidth');}if(scope==='usa'||scope==='north america'&&resolution===50){// Only works for:\n// USA states at 110m\n// USA states + Canada provinces at 50m\ncoerce('showsubunits',visible);coerce('subunitcolor');coerce('subunitwidth');}if(!isScoped){// Does not work in non-world scopes\nshow=coerce('showframe',visible);if(show){coerce('framecolor');coerce('framewidth');}}coerce('bgcolor');var fitBounds=coerce('fitbounds');// clear attributes that will get auto-filled later\nif(fitBounds){delete geoLayoutOut.projection.scale;if(isScoped){delete geoLayoutOut.center.lon;delete geoLayoutOut.center.lat;}else if(isClipped){delete geoLayoutOut.center.lon;delete geoLayoutOut.center.lat;delete geoLayoutOut.projection.rotation.lon;delete geoLayoutOut.projection.rotation.lat;delete geoLayoutOut.lonaxis.range;delete geoLayoutOut.lataxis.range;}else{delete geoLayoutOut.center.lon;delete geoLayoutOut.center.lat;delete geoLayoutOut.projection.rotation.lon;}}}},{\"../../lib\":735,\"../get_data\":820,\"../subplot_defaults\":860,\"./constants\":813,\"./layout_attributes\":816}],818:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/ /*\n * Generated by https://github.com/etpinard/d3-geo-projection-picker\n *\n * which is hand-picks projection from https://github.com/d3/d3-geo-projection\n *\n * into a CommonJS require-able module.\n */'use strict';/* eslint-disable */function addProjectionsToD3(d3){d3.geo.project=function(object,projection){var stream=projection.stream;if(!stream)throw new Error(\"not yet supported\");return(object&&d3_geo_projectObjectType.hasOwnProperty(object.type)?d3_geo_projectObjectType[object.type]:d3_geo_projectGeometry)(object,stream);};function d3_geo_projectFeature(object,stream){return{type:\"Feature\",id:object.id,properties:object.properties,geometry:d3_geo_projectGeometry(object.geometry,stream)};}function d3_geo_projectGeometry(geometry,stream){if(!geometry)return null;if(geometry.type===\"GeometryCollection\")return{type:\"GeometryCollection\",geometries:object.geometries.map(function(geometry){return d3_geo_projectGeometry(geometry,stream);})};if(!d3_geo_projectGeometryType.hasOwnProperty(geometry.type))return null;var sink=d3_geo_projectGeometryType[geometry.type];d3.geo.stream(geometry,stream(sink));return sink.result();}var d3_geo_projectObjectType={Feature:d3_geo_projectFeature,FeatureCollection:function(object,stream){return{type:\"FeatureCollection\",features:object.features.map(function(feature){return d3_geo_projectFeature(feature,stream);})};}};var d3_geo_projectPoints=[],d3_geo_projectLines=[];var d3_geo_projectPoint={point:function(x,y){d3_geo_projectPoints.push([x,y]);},result:function(){var result=!d3_geo_projectPoints.length?null:d3_geo_projectPoints.length<2?{type:\"Point\",coordinates:d3_geo_projectPoints[0]}:{type:\"MultiPoint\",coordinates:d3_geo_projectPoints};d3_geo_projectPoints=[];return result;}};var d3_geo_projectLine={lineStart:d3_geo_projectNoop,point:function(x,y){d3_geo_projectPoints.push([x,y]);},lineEnd:function(){if(d3_geo_projectPoints.length)d3_geo_projectLines.push(d3_geo_projectPoints),d3_geo_projectPoints=[];},result:function(){var result=!d3_geo_projectLines.length?null:d3_geo_projectLines.length<2?{type:\"LineString\",coordinates:d3_geo_projectLines[0]}:{type:\"MultiLineString\",coordinates:d3_geo_projectLines};d3_geo_projectLines=[];return result;}};var d3_geo_projectPolygon={polygonStart:d3_geo_projectNoop,lineStart:d3_geo_projectNoop,point:function(x,y){d3_geo_projectPoints.push([x,y]);},lineEnd:function(){var n=d3_geo_projectPoints.length;if(n){do d3_geo_projectPoints.push(d3_geo_projectPoints[0].slice());while(++n<4);d3_geo_projectLines.push(d3_geo_projectPoints),d3_geo_projectPoints=[];}},polygonEnd:d3_geo_projectNoop,result:function(){if(!d3_geo_projectLines.length)return null;var polygons=[],holes=[];d3_geo_projectLines.forEach(function(ring){if(d3_geo_projectClockwise(ring))polygons.push([ring]);else holes.push(ring);});holes.forEach(function(hole){var point=hole[0];polygons.some(function(polygon){if(d3_geo_projectContains(polygon[0],point)){polygon.push(hole);return true;}})||polygons.push([hole]);});d3_geo_projectLines=[];return!polygons.length?null:polygons.length>1?{type:\"MultiPolygon\",coordinates:polygons}:{type:\"Polygon\",coordinates:polygons[0]};}};var d3_geo_projectGeometryType={Point:d3_geo_projectPoint,MultiPoint:d3_geo_projectPoint,LineString:d3_geo_projectLine,MultiLineString:d3_geo_projectLine,Polygon:d3_geo_projectPolygon,MultiPolygon:d3_geo_projectPolygon,Sphere:d3_geo_projectPolygon};function d3_geo_projectNoop(){}function d3_geo_projectClockwise(ring){if((n=ring.length)<4)return false;var i=0,n,area=ring[n-1][1]*ring[0][0]-ring[n-1][0]*ring[0][1];while(++iy^yj>y&&x<(xj-xi)*(y-yi)/(yj-yi)+xi)contains=!contains;}return contains;}var ε=1e-6,ε2=ε*ε,π=Math.PI,halfπ=π/2,sqrtπ=Math.sqrt(π),radians=π/180,degrees=180/π;function sinci(x){return x?x/Math.sin(x):1;}function sgn(x){return x>0?1:x<0?-1:0;}function asin(x){return x>1?halfπ:x<-1?-halfπ:Math.asin(x);}function acos(x){return x>1?0:x<-1?π:Math.acos(x);}function asqrt(x){return x>0?Math.sqrt(x):0;}var projection=d3.geo.projection,projectionMutator=d3.geo.projectionMutator;d3.geo.interrupt=function(project){var lobes=[[[[-π,0],[0,halfπ],[π,0]]],[[[-π,0],[0,-halfπ],[π,0]]]];var bounds;function forward(λ,φ){var sign=φ<0?-1:+1,hemilobes=lobes[+(φ<0)];for(var i=0,n=hemilobes.length-1;ihemilobes[i][2][0];++i);var coordinates=project(λ-hemilobes[i][1][0],φ);coordinates[0]+=project(hemilobes[i][1][0],sign*φ>sign*hemilobes[i][0][1]?hemilobes[i][0][1]:φ)[0];return coordinates;}function reset(){bounds=lobes.map(function(hemilobes){return hemilobes.map(function(lobe){var x0=project(lobe[0][0],lobe[0][1])[0],x1=project(lobe[2][0],lobe[2][1])[0],y0=project(lobe[1][0],lobe[0][1])[1],y1=project(lobe[1][0],lobe[1][1])[1],t;if(y0>y1)t=y0,y0=y1,y1=t;return[[x0,y0],[x1,y1]];});});}if(project.invert)forward.invert=function(x,y){var hemibounds=bounds[+(y<0)],hemilobes=lobes[+(y<0)];for(var i=0,n=hemibounds.length;i=0;--i){var lobe=lobes[1][i],λ0=lobe[0][0]*180/π,φ0=lobe[0][1]*180/π,φ1=lobe[1][1]*180/π,λ2=lobe[2][0]*180/π,φ2=lobe[2][1]*180/π;coordinates.push(resample([[λ2-ε,φ2-ε],[λ2-ε,φ1+ε],[λ0+ε,φ1+ε],[λ0+ε,φ0-ε]],30));}return{type:\"Polygon\",coordinates:[d3.merge(coordinates)]};}function resample(coordinates,m){var i=-1,n=coordinates.length,p0=coordinates[0],p1,dx,dy,resampled=[];while(++iε;i++){var cosφ=Math.cos(φ);φ-=δ=(φ+Math.sin(φ)*(cosφ+2)-k)/(2*cosφ*(1+cosφ));}return[2/Math.sqrt(π*(4+π))*λ*(1+Math.cos(φ)),2*Math.sqrt(π/(4+π))*Math.sin(φ)];}eckert4.invert=function(x,y){var A=.5*y*Math.sqrt((4+π)/π),k=asin(A),c=Math.cos(k);return[x/(2/Math.sqrt(π*(4+π))*(1+c)),asin((k+A*(c+2))/(2+halfπ))];};(d3.geo.eckert4=function(){return projection(eckert4);}).raw=eckert4;var hammerAzimuthalEqualArea=d3.geo.azimuthalEqualArea.raw;function hammer(A,B){if(arguments.length<2)B=A;if(B===1)return hammerAzimuthalEqualArea;if(B===Infinity)return hammerQuarticAuthalic;function forward(λ,φ){var coordinates=hammerAzimuthalEqualArea(λ/B,φ);coordinates[0]*=A;return coordinates;}forward.invert=function(x,y){var coordinates=hammerAzimuthalEqualArea.invert(x/A,y);coordinates[0]*=B;return coordinates;};return forward;}function hammerProjection(){var B=2,m=projectionMutator(hammer),p=m(B);p.coefficient=function(_){if(!arguments.length)return B;return m(B=+_);};return p;}function hammerQuarticAuthalic(λ,φ){return[λ*Math.cos(φ)/Math.cos(φ/=2),2*Math.sin(φ)];}hammerQuarticAuthalic.invert=function(x,y){var φ=2*asin(y/2);return[x*Math.cos(φ/2)/Math.cos(φ),φ];};(d3.geo.hammer=hammerProjection).raw=hammer;function kavrayskiy7(λ,φ){return[3*λ/(2*π)*Math.sqrt(π*π/3-φ*φ),φ];}kavrayskiy7.invert=function(x,y){return[2/3*π*x/Math.sqrt(π*π/3-y*y),y];};(d3.geo.kavrayskiy7=function(){return projection(kavrayskiy7);}).raw=kavrayskiy7;function miller(λ,φ){return[λ,1.25*Math.log(Math.tan(π/4+.4*φ))];}miller.invert=function(x,y){return[x,2.5*Math.atan(Math.exp(.8*y))-.625*π];};(d3.geo.miller=function(){return projection(miller);}).raw=miller;function mollweideBromleyθ(Cp){return function(θ){var Cpsinθ=Cp*Math.sin(θ),i=30,δ;do θ-=δ=(θ+Math.sin(θ)-Cpsinθ)/(1+Math.cos(θ));while(Math.abs(δ)>ε&&--i>0);return θ/2;};}function mollweideBromley(Cx,Cy,Cp){var θ=mollweideBromleyθ(Cp);function forward(λ,φ){return[Cx*λ*Math.cos(φ=θ(φ)),Cy*Math.sin(φ)];}forward.invert=function(x,y){var θ=asin(y/Cy);return[x/(Cx*Math.cos(θ)),asin((2*θ+Math.sin(2*θ))/Cp)];};return forward;}var mollweideθ=mollweideBromleyθ(π),mollweide=mollweideBromley(Math.SQRT2/halfπ,Math.SQRT2,π);(d3.geo.mollweide=function(){return projection(mollweide);}).raw=mollweide;function naturalEarth(λ,φ){var φ2=φ*φ,φ4=φ2*φ2;return[λ*(.8707-.131979*φ2+φ4*(-.013791+φ4*(.003971*φ2-.001529*φ4))),φ*(1.007226+φ2*(.015085+φ4*(-.044475+.028874*φ2-.005916*φ4)))];}naturalEarth.invert=function(x,y){var φ=y,i=25,δ;do{var φ2=φ*φ,φ4=φ2*φ2;φ-=δ=(φ*(1.007226+φ2*(.015085+φ4*(-.044475+.028874*φ2-.005916*φ4)))-y)/(1.007226+φ2*(.015085*3+φ4*(-.044475*7+.028874*9*φ2-.005916*11*φ4)));}while(Math.abs(δ)>ε&&--i>0);return[x/(.8707+(φ2=φ*φ)*(-.131979+φ2*(-.013791+φ2*φ2*φ2*(.003971-.001529*φ2)))),φ];};(d3.geo.naturalEarth=function(){return projection(naturalEarth);}).raw=naturalEarth;var robinsonConstants=[[.9986,-.062],[1,0],[.9986,.062],[.9954,.124],[.99,.186],[.9822,.248],[.973,.31],[.96,.372],[.9427,.434],[.9216,.4958],[.8962,.5571],[.8679,.6176],[.835,.6769],[.7986,.7346],[.7597,.7903],[.7186,.8435],[.6732,.8936],[.6213,.9394],[.5722,.9761],[.5322,1]];robinsonConstants.forEach(function(d){d[1]*=1.0144;});function robinson(λ,φ){var i=Math.min(18,Math.abs(φ)*36/π),i0=Math.floor(i),di=i-i0,ax=(k=robinsonConstants[i0])[0],ay=k[1],bx=(k=robinsonConstants[++i0])[0],by=k[1],cx=(k=robinsonConstants[Math.min(19,++i0)])[0],cy=k[1],k;return[λ*(bx+di*(cx-ax)/2+di*di*(cx-2*bx+ax)/2),(φ>0?halfπ:-halfπ)*(by+di*(cy-ay)/2+di*di*(cy-2*by+ay)/2)];}robinson.invert=function(x,y){var yy=y/halfπ,φ=yy*90,i=Math.min(18,Math.abs(φ/5)),i0=Math.max(0,Math.floor(i));do{var ay=robinsonConstants[i0][1],by=robinsonConstants[i0+1][1],cy=robinsonConstants[Math.min(19,i0+2)][1],u=cy-ay,v=cy-2*by+ay,t=2*(Math.abs(yy)-by)/u,c=v/u,di=t*(1-c*t*(1-2*c*t));if(di>=0||i0===1){φ=(y>=0?5:-5)*(di+i);var j=50,δ;do{i=Math.min(18,Math.abs(φ)/5);i0=Math.floor(i);di=i-i0;ay=robinsonConstants[i0][1];by=robinsonConstants[i0+1][1];cy=robinsonConstants[Math.min(19,i0+2)][1];φ-=(δ=(y>=0?halfπ:-halfπ)*(by+di*(cy-ay)/2+di*di*(cy-2*by+ay)/2)-y)*degrees;}while(Math.abs(δ)>ε2&&--j>0);break;}}while(--i0>=0);var ax=robinsonConstants[i0][0],bx=robinsonConstants[i0+1][0],cx=robinsonConstants[Math.min(19,i0+2)][0];return[x/(bx+di*(cx-ax)/2+di*di*(cx-2*bx+ax)/2),φ*radians];};(d3.geo.robinson=function(){return projection(robinson);}).raw=robinson;function sinusoidal(λ,φ){return[λ*Math.cos(φ),φ];}sinusoidal.invert=function(x,y){return[x/Math.cos(y),y];};(d3.geo.sinusoidal=function(){return projection(sinusoidal);}).raw=sinusoidal;function aitoff(λ,φ){var cosφ=Math.cos(φ),sinciα=sinci(acos(cosφ*Math.cos(λ/=2)));return[2*cosφ*Math.sin(λ)*sinciα,Math.sin(φ)*sinciα];}aitoff.invert=function(x,y){if(x*x+4*y*y>π*π+ε)return;var λ=x,φ=y,i=25;do{var sinλ=Math.sin(λ),sinλ_2=Math.sin(λ/2),cosλ_2=Math.cos(λ/2),sinφ=Math.sin(φ),cosφ=Math.cos(φ),sin_2φ=Math.sin(2*φ),sin2φ=sinφ*sinφ,cos2φ=cosφ*cosφ,sin2λ_2=sinλ_2*sinλ_2,C=1-cos2φ*cosλ_2*cosλ_2,E=C?acos(cosφ*cosλ_2)*Math.sqrt(F=1/C):F=0,F,fx=2*E*cosφ*sinλ_2-x,fy=E*sinφ-y,δxδλ=F*(cos2φ*sin2λ_2+E*cosφ*cosλ_2*sin2φ),δxδφ=F*(.5*sinλ*sin_2φ-E*2*sinφ*sinλ_2),δyδλ=F*.25*(sin_2φ*sinλ_2-E*sinφ*cos2φ*sinλ),δyδφ=F*(sin2φ*cosλ_2+E*sin2λ_2*cosφ),denominator=δxδφ*δyδλ-δyδφ*δxδλ;if(!denominator)break;var δλ=(fy*δxδφ-fx*δyδφ)/denominator,δφ=(fx*δyδλ-fy*δxδλ)/denominator;λ-=δλ,φ-=δφ;}while((Math.abs(δλ)>ε||Math.abs(δφ)>ε)&&--i>0);return[λ,φ];};(d3.geo.aitoff=function(){return projection(aitoff);}).raw=aitoff;function winkel3(λ,φ){var coordinates=aitoff(λ,φ);return[(coordinates[0]+λ/halfπ)/2,(coordinates[1]+φ)/2];}winkel3.invert=function(x,y){var λ=x,φ=y,i=25;do{var cosφ=Math.cos(φ),sinφ=Math.sin(φ),sin_2φ=Math.sin(2*φ),sin2φ=sinφ*sinφ,cos2φ=cosφ*cosφ,sinλ=Math.sin(λ),cosλ_2=Math.cos(λ/2),sinλ_2=Math.sin(λ/2),sin2λ_2=sinλ_2*sinλ_2,C=1-cos2φ*cosλ_2*cosλ_2,E=C?acos(cosφ*cosλ_2)*Math.sqrt(F=1/C):F=0,F,fx=.5*(2*E*cosφ*sinλ_2+λ/halfπ)-x,fy=.5*(E*sinφ+φ)-y,δxδλ=.5*F*(cos2φ*sin2λ_2+E*cosφ*cosλ_2*sin2φ)+.5/halfπ,δxδφ=F*(sinλ*sin_2φ/4-E*sinφ*sinλ_2),δyδλ=.125*F*(sin_2φ*sinλ_2-E*sinφ*cos2φ*sinλ),δyδφ=.5*F*(sin2φ*cosλ_2+E*sin2λ_2*cosφ)+.5,denominator=δxδφ*δyδλ-δyδφ*δxδλ,δλ=(fy*δxδφ-fx*δyδφ)/denominator,δφ=(fx*δyδλ-fy*δxδλ)/denominator;λ-=δλ,φ-=δφ;}while((Math.abs(δλ)>ε||Math.abs(δφ)>ε)&&--i>0);return[λ,φ];};(d3.geo.winkel3=function(){return projection(winkel3);}).raw=winkel3;}module.exports=addProjectionsToD3;},{}],819:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var d3=_dereq_('d3');var Lib=_dereq_('../../lib');var Registry=_dereq_('../../registry');var radians=Math.PI/180;var degrees=180/Math.PI;var zoomstartStyle={cursor:'pointer'};var zoomendStyle={cursor:'auto'};function createGeoZoom(geo,geoLayout){var projection=geo.projection;var zoomConstructor;if(geoLayout._isScoped){zoomConstructor=zoomScoped;}else if(geoLayout._isClipped){zoomConstructor=zoomClipped;}else{zoomConstructor=zoomNonClipped;}// TODO add a conic-specific zoom\nreturn zoomConstructor(geo,projection);}module.exports=createGeoZoom;// common to all zoom types\nfunction initZoom(geo,projection){return d3.behavior.zoom().translate(projection.translate()).scale(projection.scale());}// sync zoom updates with user & full layout\nfunction sync(geo,projection,cb){var id=geo.id;var gd=geo.graphDiv;var layout=gd.layout;var userOpts=layout[id];var fullLayout=gd._fullLayout;var fullOpts=fullLayout[id];var preGUI={};var eventData={};function set(propStr,val){preGUI[id+'.'+propStr]=Lib.nestedProperty(userOpts,propStr).get();Registry.call('_storeDirectGUIEdit',layout,fullLayout._preGUI,preGUI);var fullNp=Lib.nestedProperty(fullOpts,propStr);if(fullNp.get()!==val){fullNp.set(val);Lib.nestedProperty(userOpts,propStr).set(val);eventData[id+'.'+propStr]=val;}}cb(set);set('projection.scale',projection.scale()/geo.fitScale);set('fitbounds',false);gd.emit('plotly_relayout',eventData);}// zoom for scoped projections\nfunction zoomScoped(geo,projection){var zoom=initZoom(geo,projection);function handleZoomstart(){d3.select(this).style(zoomstartStyle);}function handleZoom(){projection.scale(d3.event.scale).translate(d3.event.translate);geo.render();var center=projection.invert(geo.midPt);geo.graphDiv.emit('plotly_relayouting',{'geo.projection.scale':projection.scale()/geo.fitScale,'geo.center.lon':center[0],'geo.center.lat':center[1]});}function syncCb(set){var center=projection.invert(geo.midPt);set('center.lon',center[0]);set('center.lat',center[1]);}function handleZoomend(){d3.select(this).style(zoomendStyle);sync(geo,projection,syncCb);}zoom.on('zoomstart',handleZoomstart).on('zoom',handleZoom).on('zoomend',handleZoomend);return zoom;}// zoom for non-clipped projections\nfunction zoomNonClipped(geo,projection){var zoom=initZoom(geo,projection);var INSIDETOLORANCEPXS=2;var mouse0,rotate0,translate0,lastRotate,zoomPoint,mouse1,rotate1,point1,didZoom;function position(x){return projection.invert(x);}function outside(x){var pos=position(x);if(!pos)return true;var pt=projection(pos);return Math.abs(pt[0]-x[0])>INSIDETOLORANCEPXS||Math.abs(pt[1]-x[1])>INSIDETOLORANCEPXS;}function handleZoomstart(){d3.select(this).style(zoomstartStyle);mouse0=d3.mouse(this);rotate0=projection.rotate();translate0=projection.translate();lastRotate=rotate0;zoomPoint=position(mouse0);}function handleZoom(){mouse1=d3.mouse(this);if(outside(mouse0)){zoom.scale(projection.scale());zoom.translate(projection.translate());return;}projection.scale(d3.event.scale);projection.translate([translate0[0],d3.event.translate[1]]);if(!zoomPoint){mouse0=mouse1;zoomPoint=position(mouse0);}else if(position(mouse1)){point1=position(mouse1);rotate1=[lastRotate[0]+(point1[0]-zoomPoint[0]),rotate0[1],rotate0[2]];projection.rotate(rotate1);lastRotate=rotate1;}didZoom=true;geo.render();var rotate=projection.rotate();var center=projection.invert(geo.midPt);geo.graphDiv.emit('plotly_relayouting',{'geo.projection.scale':projection.scale()/geo.fitScale,'geo.center.lon':center[0],'geo.center.lat':center[1],'geo.projection.rotation.lon':-rotate[0]});}function handleZoomend(){d3.select(this).style(zoomendStyle);if(didZoom)sync(geo,projection,syncCb);}function syncCb(set){var rotate=projection.rotate();var center=projection.invert(geo.midPt);set('projection.rotation.lon',-rotate[0]);set('center.lon',center[0]);set('center.lat',center[1]);}zoom.on('zoomstart',handleZoomstart).on('zoom',handleZoom).on('zoomend',handleZoomend);return zoom;}// zoom for clipped projections\n// inspired by https://www.jasondavies.com/maps/d3.geo.zoom.js\nfunction zoomClipped(geo,projection){var view={r:projection.rotate(),k:projection.scale()};var zoom=initZoom(geo,projection);var event=d3eventDispatch(zoom,'zoomstart','zoom','zoomend');var zooming=0;var zoomOn=zoom.on;var zoomPoint;zoom.on('zoomstart',function(){d3.select(this).style(zoomstartStyle);var mouse0=d3.mouse(this);var rotate0=projection.rotate();var lastRotate=rotate0;var translate0=projection.translate();var q=quaternionFromEuler(rotate0);zoomPoint=position(projection,mouse0);zoomOn.call(zoom,'zoom',function(){var mouse1=d3.mouse(this);projection.scale(view.k=d3.event.scale);if(!zoomPoint){// if no zoomPoint, the mouse wasn't over the actual geography yet\n// maybe this point is the start... we'll find out next time!\nmouse0=mouse1;zoomPoint=position(projection,mouse0);}else if(position(projection,mouse1)){// check if the point is on the map\n// if not, don't do anything new but scale\n// if it is, then we can assume between will exist below\n// so we don't need the 'bank' function, whatever that is.\n// go back to original projection temporarily\n// except for scale... that's kind of independent?\nprojection.rotate(rotate0).translate(translate0);// calculate the new params\nvar point1=position(projection,mouse1);var between=rotateBetween(zoomPoint,point1);var newEuler=eulerFromQuaternion(multiply(q,between));var rotateAngles=view.r=unRoll(newEuler,zoomPoint,lastRotate);if(!isFinite(rotateAngles[0])||!isFinite(rotateAngles[1])||!isFinite(rotateAngles[2])){rotateAngles=lastRotate;}// update the projection\nprojection.rotate(rotateAngles);lastRotate=rotateAngles;}zoomed(event.of(this,arguments));});zoomstarted(event.of(this,arguments));}).on('zoomend',function(){d3.select(this).style(zoomendStyle);zoomOn.call(zoom,'zoom',null);zoomended(event.of(this,arguments));sync(geo,projection,syncCb);}).on('zoom.redraw',function(){geo.render();var _rotate=projection.rotate();geo.graphDiv.emit('plotly_relayouting',{'geo.projection.scale':projection.scale()/geo.fitScale,'geo.projection.rotation.lon':-_rotate[0],'geo.projection.rotation.lat':-_rotate[1]});});function zoomstarted(dispatch){if(!zooming++)dispatch({type:'zoomstart'});}function zoomed(dispatch){dispatch({type:'zoom'});}function zoomended(dispatch){if(! --zooming)dispatch({type:'zoomend'});}function syncCb(set){var _rotate=projection.rotate();set('projection.rotation.lon',-_rotate[0]);set('projection.rotation.lat',-_rotate[1]);}return d3.rebind(zoom,event,'on');}// -- helper functions for zoomClipped\nfunction position(projection,point){var spherical=projection.invert(point);return spherical&&isFinite(spherical[0])&&isFinite(spherical[1])&&cartesian(spherical);}function quaternionFromEuler(euler){var lambda=0.5*euler[0]*radians;var phi=0.5*euler[1]*radians;var gamma=0.5*euler[2]*radians;var sinLambda=Math.sin(lambda);var cosLambda=Math.cos(lambda);var sinPhi=Math.sin(phi);var cosPhi=Math.cos(phi);var sinGamma=Math.sin(gamma);var cosGamma=Math.cos(gamma);return[cosLambda*cosPhi*cosGamma+sinLambda*sinPhi*sinGamma,sinLambda*cosPhi*cosGamma-cosLambda*sinPhi*sinGamma,cosLambda*sinPhi*cosGamma+sinLambda*cosPhi*sinGamma,cosLambda*cosPhi*sinGamma-sinLambda*sinPhi*cosGamma];}function multiply(a,b){var a0=a[0];var a1=a[1];var a2=a[2];var a3=a[3];var b0=b[0];var b1=b[1];var b2=b[2];var b3=b[3];return[a0*b0-a1*b1-a2*b2-a3*b3,a0*b1+a1*b0+a2*b3-a3*b2,a0*b2-a1*b3+a2*b0+a3*b1,a0*b3+a1*b2-a2*b1+a3*b0];}function rotateBetween(a,b){if(!a||!b)return;var axis=cross(a,b);var norm=Math.sqrt(dot(axis,axis));var halfgamma=0.5*Math.acos(Math.max(-1,Math.min(1,dot(a,b))));var k=Math.sin(halfgamma)/norm;return norm&&[Math.cos(halfgamma),axis[2]*k,-axis[1]*k,axis[0]*k];}// input:\n// rotateAngles: a calculated set of Euler angles\n// pt: a point (cartesian in 3-space) to keep fixed\n// roll0: an initial roll, to be preserved\n// output:\n// a set of Euler angles that preserve the projection of pt\n// but set roll (output[2]) equal to roll0\n// note that this doesn't depend on the particular projection,\n// just on the rotation angles\nfunction unRoll(rotateAngles,pt,lastRotate){// calculate the fixed point transformed by these Euler angles\n// but with the desired roll undone\nvar ptRotated=rotateCartesian(pt,2,rotateAngles[0]);ptRotated=rotateCartesian(ptRotated,1,rotateAngles[1]);ptRotated=rotateCartesian(ptRotated,0,rotateAngles[2]-lastRotate[2]);var x=pt[0];var y=pt[1];var z=pt[2];var f=ptRotated[0];var g=ptRotated[1];var h=ptRotated[2];// the following essentially solves:\n// ptRotated = rotateCartesian(rotateCartesian(pt, 2, newYaw), 1, newPitch)\n// for newYaw and newPitch, as best it can\nvar theta=Math.atan2(y,x)*degrees;var a=Math.sqrt(x*x+y*y);var b;var newYaw1;if(Math.abs(g)>a){newYaw1=(g>0?90:-90)-theta;b=0;}else{newYaw1=Math.asin(g/a)*degrees-theta;b=Math.sqrt(a*a-g*g);}var newYaw2=180-newYaw1-2*theta;var newPitch1=(Math.atan2(h,f)-Math.atan2(z,b))*degrees;var newPitch2=(Math.atan2(h,f)-Math.atan2(z,-b))*degrees;// which is closest to lastRotate[0,1]: newYaw/Pitch or newYaw2/Pitch2?\nvar dist1=angleDistance(lastRotate[0],lastRotate[1],newYaw1,newPitch1);var dist2=angleDistance(lastRotate[0],lastRotate[1],newYaw2,newPitch2);if(dist1<=dist2)return[newYaw1,newPitch1,lastRotate[2]];else return[newYaw2,newPitch2,lastRotate[2]];}function angleDistance(yaw0,pitch0,yaw1,pitch1){var dYaw=angleMod(yaw1-yaw0);var dPitch=angleMod(pitch1-pitch0);return Math.sqrt(dYaw*dYaw+dPitch*dPitch);}// reduce an angle in degrees to [-180,180]\nfunction angleMod(angle){return(angle%360+540)%360-180;}// rotate a cartesian vector\n// axis is 0 (x), 1 (y), or 2 (z)\n// angle is in degrees\nfunction rotateCartesian(vector,axis,angle){var angleRads=angle*radians;var vectorOut=vector.slice();var ax1=axis===0?1:0;var ax2=axis===2?1:2;var cosa=Math.cos(angleRads);var sina=Math.sin(angleRads);vectorOut[ax1]=vector[ax1]*cosa-vector[ax2]*sina;vectorOut[ax2]=vector[ax2]*cosa+vector[ax1]*sina;return vectorOut;}function eulerFromQuaternion(q){return[Math.atan2(2*(q[0]*q[1]+q[2]*q[3]),1-2*(q[1]*q[1]+q[2]*q[2]))*degrees,Math.asin(Math.max(-1,Math.min(1,2*(q[0]*q[2]-q[3]*q[1]))))*degrees,Math.atan2(2*(q[0]*q[3]+q[1]*q[2]),1-2*(q[2]*q[2]+q[3]*q[3]))*degrees];}function cartesian(spherical){var lambda=spherical[0]*radians;var phi=spherical[1]*radians;var cosPhi=Math.cos(phi);return[cosPhi*Math.cos(lambda),cosPhi*Math.sin(lambda),Math.sin(phi)];}function dot(a,b){var s=0;for(var i=0,n=a.length;iMath.abs(dy)){result.boxEnd[1]=result.boxStart[1]+Math.abs(dx)*dydx*(dy>=0?1:-1);// gl-select-box clips to the plot area bounds,\n// which breaks the axis constraint, so don't allow\n// this box to go out of bounds\nif(result.boxEnd[1]dataBox[3]){result.boxEnd[1]=dataBox[3];result.boxEnd[0]=result.boxStart[0]+(dataBox[3]-result.boxStart[1])/Math.abs(dydx);}}else{result.boxEnd[0]=result.boxStart[0]+Math.abs(dy)/dydx*(dx>=0?1:-1);if(result.boxEnd[0]dataBox[2]){result.boxEnd[0]=dataBox[2];result.boxEnd[1]=result.boxStart[1]+(dataBox[2]-result.boxStart[0])*Math.abs(dydx);}}}else{// otherwise clamp small changes to the origin so we get 1D zoom\nif(smallDx)result.boxEnd[0]=result.boxStart[0];if(smallDy)result.boxEnd[1]=result.boxStart[1];}}else if(result.boxEnabled){dx=result.boxStart[0]!==result.boxEnd[0];dy=result.boxStart[1]!==result.boxEnd[1];if(dx||dy){if(dx){updateRange(0,result.boxStart[0],result.boxEnd[0]);scene.xaxis.autorange=false;}if(dy){updateRange(1,result.boxStart[1],result.boxEnd[1]);scene.yaxis.autorange=false;}scene.relayoutCallback();}else{scene.glplot.setDirty();}result.boxEnabled=false;result.boxInited=false;}else if(result.boxInited){// if box was inited but button released then - reset the box\nresult.boxInited=false;}break;case'pan':result.boxEnabled=false;result.boxInited=false;if(buttons){if(!result.panning){result.dragStart[0]=x;result.dragStart[1]=y;}if(Math.abs(result.dragStart[0]-x) 'scene'\nexports.cleanId=function cleanId(id){if(!id.match(/^scene[0-9]*$/))return;var sceneNum=id.substr(5);if(sceneNum==='1')sceneNum='';return SCENE+sceneNum;};exports.updateFx=function(gd){var fullLayout=gd._fullLayout;var subplotIds=fullLayout._subplots[GL3D];for(var i=0;i1;// some layout-wide attribute are used in all scenes\n// if 3D is the only visible plot type\nfunction getDfltFromLayout(attr){if(hasNon3D)return;var isValid=Lib.validate(layoutIn[attr],layoutAttributes[attr]);if(isValid)return layoutIn[attr];}handleSubplotDefaults(layoutIn,layoutOut,fullData,{type:GL3D,attributes:layoutAttributes,handleDefaults:handleGl3dDefaults,fullLayout:layoutOut,font:layoutOut.font,fullData:fullData,getDfltFromLayout:getDfltFromLayout,paper_bgcolor:layoutOut.paper_bgcolor,calendar:layoutOut.calendar});};function handleGl3dDefaults(sceneLayoutIn,sceneLayoutOut,coerce,opts){/*\n * Scene numbering proceeds as follows\n * scene\n * scene2\n * scene3\n *\n * and d.scene will be undefined or some number or number string\n *\n * Also write back a blank scene object to user layout so that some\n * attributes like aspectratio can be written back dynamically.\n */var bgcolor=coerce('bgcolor');var bgColorCombined=Color.combine(bgcolor,opts.paper_bgcolor);var cameraKeys=['up','center','eye'];for(var j=0;j0 not >=0)\n * note that 0's go false with the !! call\n */var hasAspect=!!coerce('aspectratio.x')&&!!coerce('aspectratio.y')&&!!coerce('aspectratio.z');var defaultAspectMode=hasAspect?'manual':'auto';var aspectMode=coerce('aspectmode',defaultAspectMode);/*\n * We need aspectratio object in all the Layouts as it is dynamically set\n * in the calculation steps, ie, we cant set the correct data now, it happens later.\n * We must also account for the case the user sends bad ratio data with 'manual' set\n * for the mode. In this case we must force change it here as the default coerce\n * misses it above.\n */if(!hasAspect){sceneLayoutIn.aspectratio=sceneLayoutOut.aspectratio={x:1,y:1,z:1};if(aspectMode==='manual')sceneLayoutOut.aspectmode='auto';/*\n * kind of like autorange - we need the calculated aspectmode back in\n * the input layout or relayout can cause problems later\n */sceneLayoutIn.aspectmode=sceneLayoutOut.aspectmode;}var fullGl3dData=getSubplotData(opts.fullData,GL3D,opts.id);supplyGl3dAxisLayoutDefaults(sceneLayoutIn,sceneLayoutOut,{font:opts.font,scene:opts.id,data:fullGl3dData,bgColor:bgColorCombined,calendar:opts.calendar,fullLayout:opts.fullLayout});Registry.getComponentMethod('annotations3d','handleDefaults')(sceneLayoutIn,sceneLayoutOut,opts);var dragmode=opts.getDfltFromLayout('dragmode');if(dragmode!==false){if(!dragmode){dragmode='orbit';if(sceneLayoutIn.camera&&sceneLayoutIn.camera.up){var x=sceneLayoutIn.camera.up.x;var y=sceneLayoutIn.camera.up.y;var z=sceneLayoutIn.camera.up.z;if(z!==0){if(!x||!y||!z){dragmode='turntable';}else if(z/Math.sqrt(x*x+y*y+z*z)>0.999){dragmode='turntable';}}}else{dragmode='turntable';}}}coerce('dragmode',dragmode);coerce('hovermode',opts.getDfltFromLayout('hovermode'));}},{\"../../../components/color\":602,\"../../../lib\":735,\"../../../registry\":866,\"../../get_data\":820,\"../../subplot_defaults\":860,\"./axis_defaults\":828,\"./layout_attributes\":831}],831:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var gl3dAxisAttrs=_dereq_('./axis_attributes');var domainAttrs=_dereq_('../../domain').attributes;var extendFlat=_dereq_('../../../lib/extend').extendFlat;var counterRegex=_dereq_('../../../lib').counterRegex;function makeCameraVector(x,y,z){return{x:{valType:'number',dflt:x,editType:'camera'},y:{valType:'number',dflt:y,editType:'camera'},z:{valType:'number',dflt:z,editType:'camera'},editType:'camera'};}module.exports={_arrayAttrRegexps:[counterRegex('scene','.annotations',true)],bgcolor:{valType:'color',dflt:'rgba(0,0,0,0)',editType:'plot'},camera:{up:extendFlat(makeCameraVector(0,0,1),{}),center:extendFlat(makeCameraVector(0,0,0),{}),eye:extendFlat(makeCameraVector(1.25,1.25,1.25),{}),projection:{type:{valType:'enumerated',values:['perspective','orthographic'],dflt:'perspective',editType:'calc'},editType:'calc'},editType:'camera'},domain:domainAttrs({name:'scene',editType:'plot'}),aspectmode:{valType:'enumerated',values:['auto','cube','data','manual'],dflt:'auto',editType:'plot',impliedEdits:{'aspectratio.x':undefined,'aspectratio.y':undefined,'aspectratio.z':undefined}},aspectratio:{// must be positive (0's are coerced to 1)\nx:{valType:'number',min:0,editType:'plot',impliedEdits:{'^aspectmode':'manual'}},y:{valType:'number',min:0,editType:'plot',impliedEdits:{'^aspectmode':'manual'}},z:{valType:'number',min:0,editType:'plot',impliedEdits:{'^aspectmode':'manual'}},editType:'plot',impliedEdits:{aspectmode:'manual'}},xaxis:gl3dAxisAttrs,yaxis:gl3dAxisAttrs,zaxis:gl3dAxisAttrs,dragmode:{valType:'enumerated',values:['orbit','turntable','zoom','pan',false],editType:'plot'},hovermode:{valType:'enumerated',values:['closest',false],dflt:'closest',editType:'modebar'},uirevision:{valType:'any',editType:'none'},editType:'plot',_deprecated:{cameraposition:{valType:'info_array',editType:'camera'}}};},{\"../../../lib\":735,\"../../../lib/extend\":726,\"../../domain\":810,\"./axis_attributes\":827}],832:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var str2RGBArray=_dereq_('../../../lib/str2rgbarray');var AXES_NAMES=['xaxis','yaxis','zaxis'];function SpikeOptions(){this.enabled=[true,true,true];this.colors=[[0,0,0,1],[0,0,0,1],[0,0,0,1]];this.drawSides=[true,true,true];this.lineWidth=[1,1,1];}var proto=SpikeOptions.prototype;proto.merge=function(sceneLayout){for(var i=0;i<3;++i){var axes=sceneLayout[AXES_NAMES[i]];if(!axes.visible){this.enabled[i]=false;this.drawSides[i]=false;continue;}this.enabled[i]=axes.showspikes;this.colors[i]=str2RGBArray(axes.spikecolor);this.drawSides[i]=axes.spikesides;this.lineWidth[i]=axes.spikethickness;}};function createSpikeOptions(layout){var result=new SpikeOptions();result.merge(layout);return result;}module.exports=createSpikeOptions;},{\"../../../lib/str2rgbarray\":758}],833:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/ /* eslint block-scoped-var: 0*/ /* eslint no-redeclare: 0*/'use strict';module.exports=computeTickMarks;var Axes=_dereq_('../../cartesian/axes');var Lib=_dereq_('../../../lib');var AXES_NAMES=['xaxis','yaxis','zaxis'];var centerPoint=[0,0,0];function contourLevelsFromTicks(ticks){var result=new Array(3);for(var i=0;i<3;++i){var tlevel=ticks[i];var clevel=new Array(tlevel.length);for(var j=0;j/g,' ');}}ticks[i]=dataTicks;axes.tickmode=tickModeCached;}}axesOptions.ticks=ticks;// Calculate tick lengths dynamically\nfor(var i=0;i<3;++i){centerPoint[i]=0.5*(scene.glplot.bounds[0][i]+scene.glplot.bounds[1][i]);for(var j=0;j<2;++j){axesOptions.bounds[j][i]=scene.glplot.bounds[j][i];}}scene.contourLevels=contourLevelsFromTicks(ticks);}},{\"../../../lib\":735,\"../../cartesian/axes\":783}],834:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';function xformMatrix(m,v){var out=[0,0,0,0];var i,j;for(i=0;i<4;++i){for(j=0;j<4;++j){out[j]+=m[4*i+j]*v[i];}}return out;}function project(camera,v){var p=xformMatrix(camera.projection,xformMatrix(camera.view,xformMatrix(camera.model,[v[0],v[1],v[2],1])));return p;}module.exports=project;},{}],835:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var glPlot3d=_dereq_('gl-plot3d');var createCamera=glPlot3d.createCamera;var createPlot=glPlot3d.createScene;var getContext=_dereq_('webgl-context');var passiveSupported=_dereq_('has-passive-events');var Registry=_dereq_('../../registry');var Lib=_dereq_('../../lib');var Axes=_dereq_('../../plots/cartesian/axes');var Fx=_dereq_('../../components/fx');var str2RGBAarray=_dereq_('../../lib/str2rgbarray');var showNoWebGlMsg=_dereq_('../../lib/show_no_webgl_msg');var project=_dereq_('./project');var createAxesOptions=_dereq_('./layout/convert');var createSpikeOptions=_dereq_('./layout/spikes');var computeTickMarks=_dereq_('./layout/tick_marks');var isMobile=_dereq_('is-mobile')({tablet:true,featureDetect:true});var STATIC_CANVAS,STATIC_CONTEXT;function Scene(options,fullLayout){// create sub container for plot\nvar sceneContainer=document.createElement('div');var plotContainer=options.container;// keep a ref to the graph div to fire hover+click events\nthis.graphDiv=options.graphDiv;// create SVG container for hover text\nvar svgContainer=document.createElementNS('http://www.w3.org/2000/svg','svg');svgContainer.style.position='absolute';svgContainer.style.top=svgContainer.style.left='0px';svgContainer.style.width=svgContainer.style.height='100%';svgContainer.style['z-index']=20;svgContainer.style['pointer-events']='none';sceneContainer.appendChild(svgContainer);this.svgContainer=svgContainer;// Tag the container with the sceneID\nsceneContainer.id=options.id;sceneContainer.style.position='absolute';sceneContainer.style.top=sceneContainer.style.left='0px';sceneContainer.style.width=sceneContainer.style.height='100%';plotContainer.appendChild(sceneContainer);this.fullLayout=fullLayout;this.id=options.id||'scene';this.fullSceneLayout=fullLayout[this.id];// Saved from last call to plot()\nthis.plotArgs=[[],{},{}];/*\n * Move this to calc step? Why does it work here?\n */this.axesOptions=createAxesOptions(fullLayout,fullLayout[this.id]);this.spikeOptions=createSpikeOptions(fullLayout[this.id]);this.container=sceneContainer;this.staticMode=!!options.staticPlot;this.pixelRatio=this.pixelRatio||options.plotGlPixelRatio||2;// Coordinate rescaling\nthis.dataScale=[1,1,1];this.contourLevels=[[],[],[]];this.convertAnnotations=Registry.getComponentMethod('annotations3d','convert');this.drawAnnotations=Registry.getComponentMethod('annotations3d','draw');this.initializeGLPlot();}var proto=Scene.prototype;proto.prepareOptions=function(){var scene=this;var opts={canvas:scene.canvas,gl:scene.gl,glOptions:{preserveDrawingBuffer:isMobile,premultipliedAlpha:true,antialias:true},container:scene.container,axes:scene.axesOptions,spikes:scene.spikeOptions,pickRadius:10,snapToData:true,autoScale:true,autoBounds:false,cameraObject:scene.camera,pixelRatio:scene.pixelRatio};// for static plots, we reuse the WebGL context\n// as WebKit doesn't collect them reliably\nif(scene.staticMode){if(!STATIC_CONTEXT){STATIC_CANVAS=document.createElement('canvas');STATIC_CONTEXT=getContext({canvas:STATIC_CANVAS,preserveDrawingBuffer:true,premultipliedAlpha:true,antialias:true});if(!STATIC_CONTEXT){throw new Error('error creating static canvas/context for image server');}}opts.gl=STATIC_CONTEXT;opts.canvas=STATIC_CANVAS;}return opts;};proto.tryCreatePlot=function(){var scene=this;var opts=scene.prepareOptions();var success=true;try{scene.glplot=createPlot(opts);}catch(e){if(scene.staticMode){success=false;}else{// try second time\ntry{// invert preserveDrawingBuffer setup which could be resulted from is-mobile not detecting the right device\nLib.warn(['webgl setup failed possibly due to',isMobile?'disabling':'enabling','preserveDrawingBuffer config.','The device may not be supported by is-mobile module!','Inverting preserveDrawingBuffer option in second attempt to create webgl scene.'].join(' '));isMobile=opts.glOptions.preserveDrawingBuffer=!opts.glOptions.preserveDrawingBuffer;scene.glplot=createPlot(opts);}catch(e){success=false;}}}return success;};proto.initializeGLCamera=function(){var scene=this;var cameraData=scene.fullSceneLayout.camera;var isOrtho=cameraData.projection.type==='orthographic';scene.camera=createCamera(scene.container,{center:[cameraData.center.x,cameraData.center.y,cameraData.center.z],eye:[cameraData.eye.x,cameraData.eye.y,cameraData.eye.z],up:[cameraData.up.x,cameraData.up.y,cameraData.up.z],_ortho:isOrtho,zoomMin:0.01,zoomMax:100,mode:'orbit'});};proto.initializeGLPlot=function(){var scene=this;scene.initializeGLCamera();var success=scene.tryCreatePlot();/*\n * createPlot will throw when webgl is not enabled in the client.\n * Lets return an instance of the module with all functions noop'd.\n * The destroy method - which will remove the container from the DOM\n * is overridden with a function that removes the container only.\n */if(!success)return showNoWebGlMsg(scene);// List of scene objects\nscene.traces={};scene.make4thDimension();var gd=scene.graphDiv;var layout=gd.layout;var makeUpdate=function(){var update={};if(scene.isCameraChanged(layout)){// camera updates\nupdate[scene.id+'.camera']=scene.getCamera();}if(scene.isAspectChanged(layout)){// scene updates\nupdate[scene.id+'.aspectratio']=scene.glplot.getAspectratio();if(layout[scene.id].aspectmode!=='manual'){scene.fullSceneLayout.aspectmode=layout[scene.id].aspectmode=update[scene.id+'.aspectmode']='manual';}}return update;};var relayoutCallback=function(scene){if(scene.fullSceneLayout.dragmode===false)return;var update=makeUpdate();scene.saveLayout(layout);scene.graphDiv.emit('plotly_relayout',update);};scene.glplot.canvas.addEventListener('mouseup',function(){relayoutCallback(scene);});scene.glplot.canvas.addEventListener('wheel',function(e){if(gd._context._scrollZoom.gl3d){if(scene.camera._ortho){var s=e.deltaX>e.deltaY?1.1:1.0/1.1;var o=scene.glplot.getAspectratio();scene.glplot.setAspectratio({x:s*o.x,y:s*o.y,z:s*o.z});}relayoutCallback(scene);}},passiveSupported?{passive:false}:false);scene.glplot.canvas.addEventListener('mousemove',function(){if(scene.fullSceneLayout.dragmode===false)return;if(scene.camera.mouseListener.buttons===0)return;var update=makeUpdate();scene.graphDiv.emit('plotly_relayouting',update);});if(!scene.staticMode){scene.glplot.canvas.addEventListener('webglcontextlost',function(event){if(gd&&gd.emit){gd.emit('plotly_webglcontextlost',{event:event,layer:scene.id});}},false);}scene.glplot.oncontextloss=function(){scene.recoverContext();};scene.glplot.onrender=function(){scene.render();};return true;};proto.render=function(){var scene=this;var gd=scene.graphDiv;var trace;// update size of svg container\nvar svgContainer=scene.svgContainer;var clientRect=scene.container.getBoundingClientRect();var width=clientRect.width;var height=clientRect.height;svgContainer.setAttributeNS(null,'viewBox','0 0 '+width+' '+height);svgContainer.setAttributeNS(null,'width',width);svgContainer.setAttributeNS(null,'height',height);computeTickMarks(scene);scene.glplot.axes.update(scene.axesOptions);// check if pick has changed\nvar keys=Object.keys(scene.traces);var lastPicked=null;var selection=scene.glplot.selection;for(var i=0;i');}else if(trace.type==='isosurface'||trace.type==='volume'){labels.valueLabel=Axes.tickText(scene._mockAxis,scene._mockAxis.d2l(selection.traceCoordinate[3]),'hover').text;vectorTx.push('value: '+labels.valueLabel);if(selection.textLabel){vectorTx.push(selection.textLabel);}tx=vectorTx.join(' ');}else{tx=selection.textLabel;}var pointData={x:selection.traceCoordinate[0],y:selection.traceCoordinate[1],z:selection.traceCoordinate[2],data:traceNow._input,fullData:traceNow,curveNumber:traceNow.index,pointNumber:ptNumber};Fx.appendArrayPointValue(pointData,traceNow,ptNumber);if(trace._module.eventData){pointData=traceNow._module.eventData(pointData,selection,traceNow,{},ptNumber);}var eventData={points:[pointData]};if(scene.fullSceneLayout.hovermode){Fx.loneHover({trace:traceNow,x:(0.5+0.5*pdata[0]/pdata[3])*width,y:(0.5-0.5*pdata[1]/pdata[3])*height,xLabel:labels.xLabel,yLabel:labels.yLabel,zLabel:labels.zLabel,text:tx,name:lastPicked.name,color:Fx.castHoverOption(traceNow,ptNumber,'bgcolor')||lastPicked.color,borderColor:Fx.castHoverOption(traceNow,ptNumber,'bordercolor'),fontFamily:Fx.castHoverOption(traceNow,ptNumber,'font.family'),fontSize:Fx.castHoverOption(traceNow,ptNumber,'font.size'),fontColor:Fx.castHoverOption(traceNow,ptNumber,'font.color'),nameLength:Fx.castHoverOption(traceNow,ptNumber,'namelength'),textAlign:Fx.castHoverOption(traceNow,ptNumber,'align'),hovertemplate:Lib.castOption(traceNow,ptNumber,'hovertemplate'),hovertemplateLabels:Lib.extendFlat({},pointData,labels),eventData:[pointData]},{container:svgContainer,gd:gd});}if(selection.buttons&&selection.distance<5){gd.emit('plotly_click',eventData);}else{gd.emit('plotly_hover',eventData);}oldEventData=eventData;}else{Fx.loneUnhover(svgContainer);gd.emit('plotly_unhover',oldEventData);}scene.drawAnnotations(scene);};proto.recoverContext=function(){var scene=this;scene.glplot.dispose();var tryRecover=function(){if(scene.glplot.gl.isContextLost()){requestAnimationFrame(tryRecover);return;}if(!scene.initializeGLPlot()){Lib.error('Catastrophic and unrecoverable WebGL error. Context lost.');return;}scene.plot.apply(scene,scene.plotArgs);};requestAnimationFrame(tryRecover);};var axisProperties=['xaxis','yaxis','zaxis'];function computeTraceBounds(scene,trace,bounds){var fullSceneLayout=scene.fullSceneLayout;for(var d=0;d<3;d++){var axisName=axisProperties[d];var axLetter=axisName.charAt(0);var ax=fullSceneLayout[axisName];var coords=trace[axLetter];var calendar=trace[axLetter+'calendar'];var len=trace['_'+axLetter+'length'];if(!Lib.isArrayOrTypedArray(coords)){bounds[0][d]=Math.min(bounds[0][d],0);bounds[1][d]=Math.max(bounds[1][d],len-1);}else{var v;for(var i=0;i<(len||coords.length);i++){if(Lib.isArrayOrTypedArray(coords[i])){for(var j=0;jsceneBounds[1][i]){sceneBounds[0][i]=-1;sceneBounds[1][i]=1;}else{var d=sceneBounds[1][i]-sceneBounds[0][i];sceneBounds[0][i]-=d/32.0;sceneBounds[1][i]+=d/32.0;}if(axis.autorange==='reversed'){// swap bounds:\nvar tmp=sceneBounds[0][i];sceneBounds[0][i]=sceneBounds[1][i];sceneBounds[1][i]=tmp;}}else{var range=axis.range;sceneBounds[0][i]=axis.r2l(range[0]);sceneBounds[1][i]=axis.r2l(range[1]);}if(sceneBounds[0][i]===sceneBounds[1][i]){sceneBounds[0][i]-=1;sceneBounds[1][i]+=1;}axisDataRange[i]=sceneBounds[1][i]-sceneBounds[0][i];// Update plot bounds\nscene.glplot.setBounds(i,{min:sceneBounds[0][i]*dataScale[i],max:sceneBounds[1][i]*dataScale[i]});}/*\n * Dynamically set the aspect ratio depending on the users aspect settings\n */var aspectRatio;var aspectmode=fullSceneLayout.aspectmode;if(aspectmode==='cube'){aspectRatio=[1,1,1];}else if(aspectmode==='manual'){var userRatio=fullSceneLayout.aspectratio;aspectRatio=[userRatio.x,userRatio.y,userRatio.z];}else if(aspectmode==='auto'||aspectmode==='data'){var axesScaleRatio=[1,1,1];// Compute axis scale per category\nfor(i=0;i<3;++i){axis=fullSceneLayout[axisProperties[i]];axisType=axis.type;var axisRatio=axisTypeRatios[axisType];axesScaleRatio[i]=Math.pow(axisRatio.acc,1.0/axisRatio.count)/dataScale[i];}if(aspectmode==='data'){aspectRatio=axesScaleRatio;}else{// i.e. 'auto' option\nif(Math.max.apply(null,axesScaleRatio)/Math.min.apply(null,axesScaleRatio)<=4){// USE DATA MODE WHEN AXIS RANGE DIMENSIONS ARE RELATIVELY EQUAL\naspectRatio=axesScaleRatio;}else{// USE EQUAL MODE WHEN AXIS RANGE DIMENSIONS ARE HIGHLY UNEQUAL\naspectRatio=[1,1,1];}}}else{throw new Error('scene.js aspectRatio was not one of the enumerated types');}/*\n * Write aspect Ratio back to user data and fullLayout so that it is modifies as user\n * manipulates the aspectmode settings and the fullLayout is up-to-date.\n */fullSceneLayout.aspectratio.x=sceneLayout.aspectratio.x=aspectRatio[0];fullSceneLayout.aspectratio.y=sceneLayout.aspectratio.y=aspectRatio[1];fullSceneLayout.aspectratio.z=sceneLayout.aspectratio.z=aspectRatio[2];/*\n * Finally assign the computed aspecratio to the glplot module. This will have an effect\n * on the next render cycle.\n */scene.glplot.setAspectratio(fullSceneLayout.aspectratio);// save 'initial' aspectratio & aspectmode view settings for modebar buttons\nif(!scene.viewInitial.aspectratio){scene.viewInitial.aspectratio={x:fullSceneLayout.aspectratio.x,y:fullSceneLayout.aspectratio.y,z:fullSceneLayout.aspectratio.z};}if(!scene.viewInitial.aspectmode){scene.viewInitial.aspectmode=fullSceneLayout.aspectmode;}// Update frame position for multi plots\nvar domain=fullSceneLayout.domain||null;var size=fullLayout._size||null;if(domain&&size){var containerStyle=scene.container.style;containerStyle.position='absolute';containerStyle.left=size.l+domain.x[0]*size.w+'px';containerStyle.top=size.t+(1-domain.y[1])*size.h+'px';containerStyle.width=size.w*(domain.x[1]-domain.x[0])+'px';containerStyle.height=size.h*(domain.y[1]-domain.y[0])+'px';}// force redraw so that promise is returned when rendering is completed\nscene.glplot.redraw();};proto.destroy=function(){var scene=this;if(!scene.glplot)return;scene.camera.mouseListener.enabled=false;scene.container.removeEventListener('wheel',scene.camera.wheelListener);scene.camera=null;scene.glplot.dispose();scene.container.parentNode.removeChild(scene.container);scene.glplot=null;};// getCameraArrays :: plotly_coords -> gl-plot3d_coords\n// inverse of getLayoutCamera\nfunction getCameraArrays(camera){return[[camera.eye.x,camera.eye.y,camera.eye.z],[camera.center.x,camera.center.y,camera.center.z],[camera.up.x,camera.up.y,camera.up.z]];}// getLayoutCamera :: gl-plot3d_coords -> plotly_coords\n// inverse of getCameraArrays\nfunction getLayoutCamera(camera){return{up:{x:camera.up[0],y:camera.up[1],z:camera.up[2]},center:{x:camera.center[0],y:camera.center[1],z:camera.center[2]},eye:{x:camera.eye[0],y:camera.eye[1],z:camera.eye[2]},projection:{type:camera._ortho===true?'orthographic':'perspective'}};}// get camera position in plotly coords from 'gl-plot3d' coords\nproto.getCamera=function(){var scene=this;scene.camera.view.recalcMatrix(scene.camera.view.lastT());return getLayoutCamera(scene.camera);};// set gl-plot3d camera position and scene aspects with a set of plotly coords\nproto.setViewport=function(sceneLayout){var scene=this;var cameraData=sceneLayout.camera;scene.camera.lookAt.apply(this,getCameraArrays(cameraData));scene.glplot.setAspectratio(sceneLayout.aspectratio);var newOrtho=cameraData.projection.type==='orthographic';var oldOrtho=scene.camera._ortho;if(newOrtho!==oldOrtho){scene.glplot.redraw();// TODO: figure out why we need to redraw here?\nscene.glplot.clearRGBA();scene.glplot.dispose();scene.initializeGLPlot();}};proto.isCameraChanged=function(layout){var scene=this;var cameraData=scene.getCamera();var cameraNestedProp=Lib.nestedProperty(layout,scene.id+'.camera');var cameraDataLastSave=cameraNestedProp.get();function same(x,y,i,j){var vectors=['up','center','eye'];var components=['x','y','z'];return y[vectors[i]]&&x[vectors[i]][components[j]]===y[vectors[i]][components[j]];}var changed=false;if(cameraDataLastSave===undefined){changed=true;}else{for(var i=0;i<3;i++){for(var j=0;j<3;j++){if(!same(cameraData,cameraDataLastSave,i,j)){changed=true;break;}}}if(!cameraDataLastSave.projection||cameraData.projection&&cameraData.projection.type!==cameraDataLastSave.projection.type){changed=true;}}return changed;};proto.isAspectChanged=function(layout){var scene=this;var aspectData=scene.glplot.getAspectratio();var aspectNestedProp=Lib.nestedProperty(layout,scene.id+'.aspectratio');var aspectDataLastSave=aspectNestedProp.get();return aspectDataLastSave===undefined||aspectDataLastSave.x!==aspectData.x||aspectDataLastSave.y!==aspectData.y||aspectDataLastSave.z!==aspectData.z;};// save camera to user layout (i.e. gd.layout)\nproto.saveLayout=function(layout){var scene=this;var fullLayout=scene.fullLayout;var cameraData;var cameraNestedProp;var cameraDataLastSave;var aspectData;var aspectNestedProp;var aspectDataLastSave;var cameraChanged=scene.isCameraChanged(layout);var aspectChanged=scene.isAspectChanged(layout);var hasChanged=cameraChanged||aspectChanged;if(hasChanged){var preGUI={};if(cameraChanged){cameraData=scene.getCamera();cameraNestedProp=Lib.nestedProperty(layout,scene.id+'.camera');cameraDataLastSave=cameraNestedProp.get();preGUI[scene.id+'.camera']=cameraDataLastSave;}if(aspectChanged){aspectData=scene.glplot.getAspectratio();aspectNestedProp=Lib.nestedProperty(layout,scene.id+'.aspectratio');aspectDataLastSave=aspectNestedProp.get();preGUI[scene.id+'.aspectratio']=aspectDataLastSave;}Registry.call('_storeDirectGUIEdit',layout,fullLayout._preGUI,preGUI);if(cameraChanged){cameraNestedProp.set(cameraData);var cameraFullNP=Lib.nestedProperty(fullLayout,scene.id+'.camera');cameraFullNP.set(cameraData);}if(aspectChanged){aspectNestedProp.set(aspectData);var aspectFullNP=Lib.nestedProperty(fullLayout,scene.id+'.aspectratio');aspectFullNP.set(aspectData);scene.glplot.redraw();}}return hasChanged;};proto.updateFx=function(dragmode,hovermode){var scene=this;var camera=scene.camera;if(camera){// rotate and orbital are synonymous\nif(dragmode==='orbit'){camera.mode='orbit';camera.keyBindingMode='rotate';}else if(dragmode==='turntable'){camera.up=[0,0,1];camera.mode='turntable';camera.keyBindingMode='rotate';// The setter for camera.mode animates the transition to z-up,\n// but only if we *don't* explicitly set z-up earlier via the\n// relayout. So push `up` back to layout & fullLayout manually now.\nvar gd=scene.graphDiv;var fullLayout=gd._fullLayout;var fullCamera=scene.fullSceneLayout.camera;var x=fullCamera.up.x;var y=fullCamera.up.y;var z=fullCamera.up.z;// only push `up` back to (full)layout if it's going to change\nif(z/Math.sqrt(x*x+y*y+z*z)<0.999){var attr=scene.id+'.camera.up';var zUp={x:0,y:0,z:1};var edits={};edits[attr]=zUp;var layout=gd.layout;Registry.call('_storeDirectGUIEdit',layout,fullLayout._preGUI,edits);fullCamera.up=zUp;Lib.nestedProperty(layout,attr).set(zUp);}}else{// none rotation modes [pan or zoom]\ncamera.keyBindingMode=dragmode;}}// to put dragmode and hovermode on the same grounds from relayout\nscene.fullSceneLayout.hovermode=hovermode;};function flipPixels(pixels,w,h){for(var i=0,q=h-1;i0){var q=255/a;for(var l=0;l<3;++l){// RGB\npixels[k+l]=Math.min(q*pixels[k+l],255);}}}}}proto.toImage=function(format){var scene=this;if(!format)format='png';if(scene.staticMode)scene.container.appendChild(STATIC_CANVAS);// Force redraw\nscene.glplot.redraw();// Grab context and yank out pixels\nvar gl=scene.glplot.gl;var w=gl.drawingBufferWidth;var h=gl.drawingBufferHeight;gl.bindFramebuffer(gl.FRAMEBUFFER,null);var pixels=new Uint8Array(w*h*4);gl.readPixels(0,0,w,h,gl.RGBA,gl.UNSIGNED_BYTE,pixels);flipPixels(pixels,w,h);correctRGB(pixels,w,h);var canvas=document.createElement('canvas');canvas.width=w;canvas.height=h;var context=canvas.getContext('2d');var imageData=context.createImageData(w,h);imageData.data.set(pixels);context.putImageData(imageData,0,0);var dataURL;switch(format){case'jpeg':dataURL=canvas.toDataURL('image/jpeg');break;case'webp':dataURL=canvas.toDataURL('image/webp');break;default:dataURL=canvas.toDataURL('image/png');}if(scene.staticMode)scene.container.removeChild(STATIC_CANVAS);return dataURL;};proto.setConvert=function(){var scene=this;for(var i=0;i<3;i++){var ax=scene.fullSceneLayout[axisProperties[i]];Axes.setConvert(ax,scene.fullLayout);ax.setScale=Lib.noop;}};proto.make4thDimension=function(){var scene=this;var gd=scene.graphDiv;var fullLayout=gd._fullLayout;// mock axis for hover formatting\nscene._mockAxis={type:'linear',showexponent:'all',exponentformat:'B'};Axes.setConvert(scene._mockAxis,fullLayout);};module.exports=Scene;},{\"../../components/fx\":642,\"../../lib\":735,\"../../lib/show_no_webgl_msg\":756,\"../../lib/str2rgbarray\":758,\"../../plots/cartesian/axes\":783,\"../../registry\":866,\"./layout/convert\":829,\"./layout/spikes\":832,\"./layout/tick_marks\":833,\"./project\":834,\"gl-plot3d\":300,\"has-passive-events\":414,\"is-mobile\":424,\"webgl-context\":565}],836:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';module.exports=function zip3(x,y,z,len){len=len||x.length;var result=new Array(len);for(var i=0;i© OpenStreetMap',tiles:['https://a.tile.openstreetmap.org/{z}/{x}/{y}.png','https://b.tile.openstreetmap.org/{z}/{x}/{y}.png'],tileSize:256}},layers:[{id:'plotly-osm-tiles',type:'raster',source:'plotly-osm-tiles',minzoom:0,maxzoom:22}]},'white-bg':{id:'white-bg',version:8,sources:{},layers:[{id:'white-bg',type:'background',paint:{'background-color':'#FFFFFF'},minzoom:0,maxzoom:22}]},'carto-positron':{id:'carto-positron',version:8,sources:{'plotly-carto-positron':{type:'raster',attribution:'© CARTO ',tiles:['https://cartodb-basemaps-c.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png'],tileSize:256}},layers:[{id:'plotly-carto-positron',type:'raster',source:'plotly-carto-positron',minzoom:0,maxzoom:22}]},'carto-darkmatter':{id:'carto-darkmatter',version:8,sources:{'plotly-carto-darkmatter':{type:'raster',attribution:'© CARTO ',tiles:['https://cartodb-basemaps-c.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png'],tileSize:256}},layers:[{id:'plotly-carto-darkmatter',type:'raster',source:'plotly-carto-darkmatter',minzoom:0,maxzoom:22}]},'stamen-terrain':{id:'stamen-terrain',version:8,sources:{'plotly-stamen-terrain':{type:'raster',attribution:'Map tiles by Stamen Design , under CC BY 3.0 | Data by OpenStreetMap , under ODbL .',tiles:['https://stamen-tiles.a.ssl.fastly.net/terrain/{z}/{x}/{y}.png'],tileSize:256}},layers:[{id:'plotly-stamen-terrain',type:'raster',source:'plotly-stamen-terrain',minzoom:0,maxzoom:22}]},'stamen-toner':{id:'stamen-toner',version:8,sources:{'plotly-stamen-toner':{type:'raster',attribution:'Map tiles by Stamen Design , under CC BY 3.0 | Data by OpenStreetMap , under ODbL .',tiles:['https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png'],tileSize:256}},layers:[{id:'plotly-stamen-toner',type:'raster',source:'plotly-stamen-toner',minzoom:0,maxzoom:22}]},'stamen-watercolor':{id:'stamen-watercolor',version:8,sources:{'plotly-stamen-watercolor':{type:'raster',attribution:'Map tiles by Stamen Design , under CC BY 3.0 | Data by OpenStreetMap , under CC BY SA .',tiles:['https://stamen-tiles.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.png'],tileSize:256}},layers:[{id:'plotly-stamen-watercolor',type:'raster',source:'plotly-stamen-watercolor',minzoom:0,maxzoom:22}]}};var styleValuesNonMapbox=Object.keys(stylesNonMapbox);module.exports={requiredVersion:requiredVersion,styleUrlPrefix:'mapbox://styles/mapbox/',styleUrlSuffix:'v9',styleValuesMapbox:['basic','streets','outdoors','light','dark','satellite','satellite-streets'],styleValueDflt:'basic',stylesNonMapbox:stylesNonMapbox,styleValuesNonMapbox:styleValuesNonMapbox,traceLayerPrefix:'plotly-trace-layer-',layoutLayerPrefix:'plotly-layout-layer-',wrongVersionErrorMsg:['Your custom plotly.js bundle is not using the correct mapbox-gl version','Please install mapbox-gl@'+requiredVersion+'.'].join('\\n'),noAccessTokenErrorMsg:['Missing Mapbox access token.','Mapbox trace type require a Mapbox access token to be registered.','For example:',' Plotly.plot(gd, data, layout, { mapboxAccessToken: \\'my-access-token\\' });','More info here: https://www.mapbox.com/help/define-access-token/'].join('\\n'),missingStyleErrorMsg:['No valid mapbox style found, please set `mapbox.style` to one of:',styleValuesNonMapbox.join(', '),'or register a Mapbox access token to use a Mapbox-served style.'].join('\\n'),multipleTokensErrorMsg:['Set multiple mapbox access token across different mapbox subplot,','using first token found as mapbox-gl does not allow multiple'+'access tokens on the same page.'].join('\\n'),mapOnErrorMsg:'Mapbox error.',// Mapbox logo for static export\nmapboxLogo:{path0:'m 10.5,1.24 c -5.11,0 -9.25,4.15 -9.25,9.25 0,5.1 4.15,9.25 9.25,9.25 5.1,0 9.25,-4.15 9.25,-9.25 0,-5.11 -4.14,-9.25 -9.25,-9.25 z m 4.39,11.53 c -1.93,1.93 -4.78,2.31 -6.7,2.31 -0.7,0 -1.41,-0.05 -2.1,-0.16 0,0 -1.02,-5.64 2.14,-8.81 0.83,-0.83 1.95,-1.28 3.13,-1.28 1.27,0 2.49,0.51 3.39,1.42 1.84,1.84 1.89,4.75 0.14,6.52 z',path1:'M 10.5,-0.01 C 4.7,-0.01 0,4.7 0,10.49 c 0,5.79 4.7,10.5 10.5,10.5 5.8,0 10.5,-4.7 10.5,-10.5 C 20.99,4.7 16.3,-0.01 10.5,-0.01 Z m 0,19.75 c -5.11,0 -9.25,-4.15 -9.25,-9.25 0,-5.1 4.14,-9.26 9.25,-9.26 5.11,0 9.25,4.15 9.25,9.25 0,5.13 -4.14,9.26 -9.25,9.26 z',path2:'M 14.74,6.25 C 12.9,4.41 9.98,4.35 8.23,6.1 5.07,9.27 6.09,14.91 6.09,14.91 c 0,0 5.64,1.02 8.81,-2.14 C 16.64,11 16.59,8.09 14.74,6.25 Z m -2.27,4.09 -0.91,1.87 -0.9,-1.87 -1.86,-0.91 1.86,-0.9 0.9,-1.87 0.91,1.87 1.86,0.9 z',polygon:'11.56,12.21 10.66,10.34 8.8,9.43 10.66,8.53 11.56,6.66 12.47,8.53 14.33,9.43 12.47,10.34'},// a subset of node_modules/mapbox-gl/dist/mapbox-gl.css\nstyleRules:{map:'overflow:hidden;position:relative;','missing-css':'display:none;','canary':'background-color:salmon;',// Reusing CSS directives from: https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.1/mapbox-gl.css\n'ctrl-bottom-left':'position: absolute; pointer-events: none; z-index: 2; bottom: 0; left: 0;','ctrl-bottom-right':'position: absolute; pointer-events: none; z-index: 2; right: 0; bottom: 0;','ctrl':'clear: both; pointer-events: auto; transform: translate(0, 0);',// Compact ctrl\n'ctrl-attrib.mapboxgl-compact .mapboxgl-ctrl-attrib-inner':'display: none;','ctrl-attrib.mapboxgl-compact:hover .mapboxgl-ctrl-attrib-inner':'display: block; margin-top:2px','ctrl-attrib.mapboxgl-compact:hover':'padding: 2px 24px 2px 4px; visibility: visible; margin-top: 6px;','ctrl-attrib.mapboxgl-compact::after':'content: \"\"; cursor: pointer; position: absolute; background-image: url(\\'data:image/svg+xml;charset=utf-8,%3Csvg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"%3E %3Cpath fill=\"%23333333\" fill-rule=\"evenodd\" d=\"M4,10a6,6 0 1,0 12,0a6,6 0 1,0 -12,0 M9,7a1,1 0 1,0 2,0a1,1 0 1,0 -2,0 M9,10a1,1 0 1,1 2,0l0,3a1,1 0 1,1 -2,0\"/%3E %3C/svg%3E\\'); background-color: rgba(255, 255, 255, 0.5); width: 24px; height: 24px; box-sizing: border-box; border-radius: 12px;','ctrl-attrib.mapboxgl-compact':'min-height: 20px; padding: 0; margin: 10px; position: relative; background-color: #fff; border-radius: 3px 12px 12px 3px;','ctrl-bottom-right > .mapboxgl-ctrl-attrib.mapboxgl-compact::after':'bottom: 0; right: 0','ctrl-bottom-left > .mapboxgl-ctrl-attrib.mapboxgl-compact::after':'bottom: 0; left: 0','ctrl-bottom-left .mapboxgl-ctrl':'margin: 0 0 10px 10px; float: left;','ctrl-bottom-right .mapboxgl-ctrl':'margin: 0 10px 10px 0; float: right;','ctrl-attrib':'color: rgba(0, 0, 0, 0.75); text-decoration: none; font-size: 12px','ctrl-attrib a':'color: rgba(0, 0, 0, 0.75); text-decoration: none; font-size: 12px','ctrl-attrib a:hover':'color: inherit; text-decoration: underline;','ctrl-attrib .mapbox-improve-map':'font-weight: bold; margin-left: 2px;','attrib-empty':'display: none;',// Compact Mapbox logo without text\n'ctrl-logo':'display:block; width: 21px; height: 21px; background-image: url(\\'data:image/svg+xml;charset=utf-8,%3C?xml version=\"1.0\" encoding=\"utf-8\"?%3E %3Csvg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"0 0 21 21\" style=\"enable-background:new 0 0 21 21;\" xml:space=\"preserve\"%3E%3Cg transform=\"translate(0,0.01)\"%3E%3Cpath d=\"m 10.5,1.24 c -5.11,0 -9.25,4.15 -9.25,9.25 0,5.1 4.15,9.25 9.25,9.25 5.1,0 9.25,-4.15 9.25,-9.25 0,-5.11 -4.14,-9.25 -9.25,-9.25 z m 4.39,11.53 c -1.93,1.93 -4.78,2.31 -6.7,2.31 -0.7,0 -1.41,-0.05 -2.1,-0.16 0,0 -1.02,-5.64 2.14,-8.81 0.83,-0.83 1.95,-1.28 3.13,-1.28 1.27,0 2.49,0.51 3.39,1.42 1.84,1.84 1.89,4.75 0.14,6.52 z\" style=\"opacity:0.9;fill:%23ffffff;enable-background:new\" class=\"st0\"/%3E%3Cpath d=\"M 10.5,-0.01 C 4.7,-0.01 0,4.7 0,10.49 c 0,5.79 4.7,10.5 10.5,10.5 5.8,0 10.5,-4.7 10.5,-10.5 C 20.99,4.7 16.3,-0.01 10.5,-0.01 Z m 0,19.75 c -5.11,0 -9.25,-4.15 -9.25,-9.25 0,-5.1 4.14,-9.26 9.25,-9.26 5.11,0 9.25,4.15 9.25,9.25 0,5.13 -4.14,9.26 -9.25,9.26 z\" style=\"opacity:0.35;enable-background:new\" class=\"st1\"/%3E%3Cpath d=\"M 14.74,6.25 C 12.9,4.41 9.98,4.35 8.23,6.1 5.07,9.27 6.09,14.91 6.09,14.91 c 0,0 5.64,1.02 8.81,-2.14 C 16.64,11 16.59,8.09 14.74,6.25 Z m -2.27,4.09 -0.91,1.87 -0.9,-1.87 -1.86,-0.91 1.86,-0.9 0.9,-1.87 0.91,1.87 1.86,0.9 z\" style=\"opacity:0.35;enable-background:new\" class=\"st1\"/%3E%3Cpolygon points=\"11.56,12.21 10.66,10.34 8.8,9.43 10.66,8.53 11.56,6.66 12.47,8.53 14.33,9.43 12.47,10.34 \" style=\"opacity:0.9;fill:%23ffffff;enable-background:new\" class=\"st0\"/%3E%3C/g%3E%3C/svg%3E\\')'// Mapbox logo WITH text below (commented out for now)\n// 'ctrl-logo': 'width: 85px; height: 21px; margin: 0 0 -3px -3px; display: block; background-repeat: no-repeat; cursor: pointer; background-image: url(\\'data:image/svg+xml;charset=utf-8,%3C?xml version=\"1.0\" encoding=\"utf-8\"?%3E%3Csvg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"0 0 84.49 21\" style=\"enable-background:new 0 0 84.49 21;\" xml:space=\"preserve\"%3E%3Cg%3E %3Cpath class=\"st0\" style=\"opacity:0.9; fill: %23FFFFFF; enable-background: new;\" d=\"M83.25,14.26c0,0.12-0.09,0.21-0.21,0.21h-1.61c-0.13,0-0.24-0.06-0.3-0.17l-1.44-2.39l-1.44,2.39 c-0.06,0.11-0.18,0.17-0.3,0.17h-1.61c-0.04,0-0.08-0.01-0.12-0.03c-0.09-0.06-0.13-0.19-0.06-0.28l0,0l2.43-3.68L76.2,6.84 c-0.02-0.03-0.03-0.07-0.03-0.12c0-0.12,0.09-0.21,0.21-0.21h1.61c0.13,0,0.24,0.06,0.3,0.17l1.41,2.36l1.4-2.35 c0.06-0.11,0.18-0.17,0.3-0.17H83c0.04,0,0.08,0.01,0.12,0.03c0.09,0.06,0.13,0.19,0.06,0.28l0,0l-2.37,3.63l2.43,3.67 C83.24,14.18,83.25,14.22,83.25,14.26z\"/%3E %3Cpath class=\"st0\" style=\"opacity:0.9; fill: %23FFFFFF; enable-background: new;\" d=\"M66.24,9.59c-0.39-1.88-1.96-3.28-3.84-3.28c-1.03,0-2.03,0.42-2.73,1.18V3.51c0-0.13-0.1-0.23-0.23-0.23h-1.4 c-0.13,0-0.23,0.11-0.23,0.23v10.72c0,0.13,0.1,0.23,0.23,0.23h1.4c0.13,0,0.23-0.11,0.23-0.23V13.5c0.71,0.75,1.7,1.18,2.73,1.18 c1.88,0,3.45-1.41,3.84-3.29C66.37,10.79,66.37,10.18,66.24,9.59L66.24,9.59z M62.08,13c-1.32,0-2.39-1.11-2.41-2.48v-0.06 c0.02-1.38,1.09-2.48,2.41-2.48s2.42,1.12,2.42,2.51S63.41,13,62.08,13z\"/%3E %3Cpath class=\"st0\" style=\"opacity:0.9; fill: %23FFFFFF; enable-background: new;\" d=\"M71.67,6.32c-1.98-0.01-3.72,1.35-4.16,3.29c-0.13,0.59-0.13,1.19,0,1.77c0.44,1.94,2.17,3.32,4.17,3.3 c2.35,0,4.26-1.87,4.26-4.19S74.04,6.32,71.67,6.32z M71.65,13.01c-1.33,0-2.42-1.12-2.42-2.51s1.08-2.52,2.42-2.52 c1.33,0,2.42,1.12,2.42,2.51S72.99,13,71.65,13.01L71.65,13.01z\"/%3E %3Cpath class=\"st1\" style=\"opacity:0.35; enable-background:new;\" d=\"M62.08,7.98c-1.32,0-2.39,1.11-2.41,2.48v0.06C59.68,11.9,60.75,13,62.08,13s2.42-1.12,2.42-2.51 S63.41,7.98,62.08,7.98z M62.08,11.76c-0.63,0-1.14-0.56-1.17-1.25v-0.04c0.01-0.69,0.54-1.25,1.17-1.25 c0.63,0,1.17,0.57,1.17,1.27C63.24,11.2,62.73,11.76,62.08,11.76z\"/%3E %3Cpath class=\"st1\" style=\"opacity:0.35; enable-background:new;\" d=\"M71.65,7.98c-1.33,0-2.42,1.12-2.42,2.51S70.32,13,71.65,13s2.42-1.12,2.42-2.51S72.99,7.98,71.65,7.98z M71.65,11.76c-0.64,0-1.17-0.57-1.17-1.27c0-0.7,0.53-1.26,1.17-1.26s1.17,0.57,1.17,1.27C72.82,11.21,72.29,11.76,71.65,11.76z\"/%3E %3Cpath class=\"st0\" style=\"opacity:0.9; fill: %23FFFFFF; enable-background: new;\" d=\"M45.74,6.53h-1.4c-0.13,0-0.23,0.11-0.23,0.23v0.73c-0.71-0.75-1.7-1.18-2.73-1.18 c-2.17,0-3.94,1.87-3.94,4.19s1.77,4.19,3.94,4.19c1.04,0,2.03-0.43,2.73-1.19v0.73c0,0.13,0.1,0.23,0.23,0.23h1.4 c0.13,0,0.23-0.11,0.23-0.23V6.74c0-0.12-0.09-0.22-0.22-0.22C45.75,6.53,45.75,6.53,45.74,6.53z M44.12,10.53 C44.11,11.9,43.03,13,41.71,13s-2.42-1.12-2.42-2.51s1.08-2.52,2.4-2.52c1.33,0,2.39,1.11,2.41,2.48L44.12,10.53z\"/%3E %3Cpath class=\"st1\" style=\"opacity:0.35; enable-background:new;\" d=\"M41.71,7.98c-1.33,0-2.42,1.12-2.42,2.51S40.37,13,41.71,13s2.39-1.11,2.41-2.48v-0.06 C44.1,9.09,43.03,7.98,41.71,7.98z M40.55,10.49c0-0.7,0.52-1.27,1.17-1.27c0.64,0,1.14,0.56,1.17,1.25v0.04 c-0.01,0.68-0.53,1.24-1.17,1.24C41.08,11.75,40.55,11.19,40.55,10.49z\"/%3E %3Cpath class=\"st0\" style=\"opacity:0.9; fill: %23FFFFFF; enable-background: new;\" d=\"M52.41,6.32c-1.03,0-2.03,0.42-2.73,1.18V6.75c0-0.13-0.1-0.23-0.23-0.23h-1.4c-0.13,0-0.23,0.11-0.23,0.23 v10.72c0,0.13,0.1,0.23,0.23,0.23h1.4c0.13,0,0.23-0.1,0.23-0.23V13.5c0.71,0.75,1.7,1.18,2.74,1.18c2.17,0,3.94-1.87,3.94-4.19 S54.58,6.32,52.41,6.32z M52.08,13.01c-1.32,0-2.39-1.11-2.42-2.48v-0.07c0.02-1.38,1.09-2.49,2.4-2.49c1.32,0,2.41,1.12,2.41,2.51 S53.4,13,52.08,13.01L52.08,13.01z\"/%3E %3Cpath class=\"st1\" style=\"opacity:0.35; enable-background:new;\" d=\"M52.08,7.98c-1.32,0-2.39,1.11-2.42,2.48v0.06c0.03,1.38,1.1,2.48,2.42,2.48s2.41-1.12,2.41-2.51 S53.4,7.98,52.08,7.98z M52.08,11.76c-0.63,0-1.14-0.56-1.17-1.25v-0.04c0.01-0.69,0.54-1.25,1.17-1.25c0.63,0,1.17,0.58,1.17,1.27 S52.72,11.76,52.08,11.76z\"/%3E %3Cpath class=\"st0\" style=\"opacity:0.9; fill: %23FFFFFF; enable-background: new;\" d=\"M36.08,14.24c0,0.13-0.1,0.23-0.23,0.23h-1.41c-0.13,0-0.23-0.11-0.23-0.23V9.68c0-0.98-0.74-1.71-1.62-1.71 c-0.8,0-1.46,0.7-1.59,1.62l0.01,4.66c0,0.13-0.11,0.23-0.23,0.23h-1.41c-0.13,0-0.23-0.11-0.23-0.23V9.68 c0-0.98-0.74-1.71-1.62-1.71c-0.85,0-1.54,0.79-1.6,1.8v4.48c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23V6.74 c0.01-0.13,0.1-0.22,0.23-0.22h1.4c0.13,0,0.22,0.11,0.23,0.22V7.4c0.5-0.68,1.3-1.09,2.16-1.1h0.03c1.09,0,2.09,0.6,2.6,1.55 c0.45-0.95,1.4-1.55,2.44-1.56c1.62,0,2.93,1.25,2.9,2.78L36.08,14.24z\"/%3E %3Cpath class=\"st1\" style=\"opacity:0.35; enable-background:new;\" d=\"M84.34,13.59l-0.07-0.13l-1.96-2.99l1.94-2.95c0.44-0.67,0.26-1.56-0.41-2.02c-0.02,0-0.03,0-0.04-0.01 c-0.23-0.15-0.5-0.22-0.78-0.22h-1.61c-0.56,0-1.08,0.29-1.37,0.78L79.72,6.6l-0.34-0.56C79.09,5.56,78.57,5.27,78,5.27h-1.6 c-0.6,0-1.13,0.37-1.35,0.92c-2.19-1.66-5.28-1.47-7.26,0.45c-0.35,0.34-0.65,0.72-0.89,1.14c-0.9-1.62-2.58-2.72-4.5-2.72 c-0.5,0-1.01,0.07-1.48,0.23V3.51c0-0.82-0.66-1.48-1.47-1.48h-1.4c-0.81,0-1.47,0.66-1.47,1.47v3.75 c-0.95-1.36-2.5-2.18-4.17-2.19c-0.74,0-1.46,0.16-2.12,0.47c-0.24-0.17-0.54-0.26-0.84-0.26h-1.4c-0.45,0-0.87,0.21-1.15,0.56 c-0.02-0.03-0.04-0.05-0.07-0.08c-0.28-0.3-0.68-0.47-1.09-0.47h-1.39c-0.3,0-0.6,0.09-0.84,0.26c-0.67-0.3-1.39-0.46-2.12-0.46 c-1.83,0-3.43,1-4.37,2.5c-0.2-0.46-0.48-0.89-0.83-1.25c-0.8-0.81-1.89-1.25-3.02-1.25h-0.01c-0.89,0.01-1.75,0.33-2.46,0.88 c-0.74-0.57-1.64-0.88-2.57-0.88H28.1c-0.29,0-0.58,0.03-0.86,0.11c-0.28,0.06-0.56,0.16-0.82,0.28c-0.21-0.12-0.45-0.18-0.7-0.18 h-1.4c-0.82,0-1.47,0.66-1.47,1.47v7.5c0,0.82,0.66,1.47,1.47,1.47h1.4c0.82,0,1.48-0.66,1.48-1.48l0,0V9.79 c0.03-0.36,0.23-0.59,0.36-0.59c0.18,0,0.38,0.18,0.38,0.47v4.57c0,0.82,0.66,1.47,1.47,1.47h1.41c0.82,0,1.47-0.66,1.47-1.47 l-0.01-4.57c0.06-0.32,0.25-0.47,0.35-0.47c0.18,0,0.38,0.18,0.38,0.47v4.57c0,0.82,0.66,1.47,1.47,1.47h1.41 c0.82,0,1.47-0.66,1.47-1.47v-0.38c0.96,1.29,2.46,2.06,4.06,2.06c0.74,0,1.46-0.16,2.12-0.47c0.24,0.17,0.54,0.26,0.84,0.26h1.39 c0.3,0,0.6-0.09,0.84-0.26v2.01c0,0.82,0.66,1.47,1.47,1.47h1.4c0.82,0,1.47-0.66,1.47-1.47v-1.77c0.48,0.15,0.99,0.23,1.49,0.22 c1.7,0,3.22-0.87,4.17-2.2v0.52c0,0.82,0.66,1.47,1.47,1.47h1.4c0.3,0,0.6-0.09,0.84-0.26c0.66,0.31,1.39,0.47,2.12,0.47 c1.92,0,3.6-1.1,4.49-2.73c1.54,2.65,4.95,3.53,7.58,1.98c0.18-0.11,0.36-0.22,0.53-0.36c0.22,0.55,0.76,0.91,1.35,0.9H78 c0.56,0,1.08-0.29,1.37-0.78l0.37-0.61l0.37,0.61c0.29,0.48,0.81,0.78,1.38,0.78h1.6c0.81,0,1.46-0.66,1.45-1.46 C84.49,14.02,84.44,13.8,84.34,13.59L84.34,13.59z M35.86,14.47h-1.41c-0.13,0-0.23-0.11-0.23-0.23V9.68 c0-0.98-0.74-1.71-1.62-1.71c-0.8,0-1.46,0.7-1.59,1.62l0.01,4.66c0,0.13-0.1,0.23-0.23,0.23h-1.41c-0.13,0-0.23-0.11-0.23-0.23 V9.68c0-0.98-0.74-1.71-1.62-1.71c-0.85,0-1.54,0.79-1.6,1.8v4.48c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23 V6.74c0.01-0.13,0.11-0.22,0.23-0.22h1.4c0.13,0,0.22,0.11,0.23,0.22V7.4c0.5-0.68,1.3-1.09,2.16-1.1h0.03 c1.09,0,2.09,0.6,2.6,1.55c0.45-0.95,1.4-1.55,2.44-1.56c1.62,0,2.93,1.25,2.9,2.78l0.01,5.16C36.09,14.36,35.98,14.46,35.86,14.47 L35.86,14.47z M45.97,14.24c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23V13.5c-0.7,0.76-1.69,1.18-2.72,1.18 c-2.17,0-3.94-1.87-3.94-4.19s1.77-4.19,3.94-4.19c1.03,0,2.02,0.43,2.73,1.18V6.74c0-0.13,0.1-0.23,0.23-0.23h1.4 c0.12-0.01,0.22,0.08,0.23,0.21c0,0.01,0,0.01,0,0.02v7.51h-0.01V14.24z M52.41,14.67c-1.03,0-2.02-0.43-2.73-1.18v3.97 c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.1-0.23-0.23V6.75c0-0.13,0.1-0.22,0.23-0.22h1.4c0.13,0,0.23,0.11,0.23,0.23v0.73 c0.71-0.76,1.7-1.18,2.73-1.18c2.17,0,3.94,1.86,3.94,4.18S54.58,14.67,52.41,14.67z M66.24,11.39c-0.39,1.87-1.96,3.29-3.84,3.29 c-1.03,0-2.02-0.43-2.73-1.18v0.73c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23V3.51c0-0.13,0.1-0.23,0.23-0.23 h1.4c0.13,0,0.23,0.11,0.23,0.23v3.97c0.71-0.75,1.7-1.18,2.73-1.17c1.88,0,3.45,1.4,3.84,3.28C66.37,10.19,66.37,10.8,66.24,11.39 L66.24,11.39L66.24,11.39z M71.67,14.68c-2,0.01-3.73-1.35-4.17-3.3c-0.13-0.59-0.13-1.19,0-1.77c0.44-1.94,2.17-3.31,4.17-3.3 c2.36,0,4.26,1.87,4.26,4.19S74.03,14.68,71.67,14.68L71.67,14.68z M83.04,14.47h-1.61c-0.13,0-0.24-0.06-0.3-0.17l-1.44-2.39 l-1.44,2.39c-0.06,0.11-0.18,0.17-0.3,0.17h-1.61c-0.04,0-0.08-0.01-0.12-0.03c-0.09-0.06-0.13-0.19-0.06-0.28l0,0l2.43-3.68 L76.2,6.84c-0.02-0.03-0.03-0.07-0.03-0.12c0-0.12,0.09-0.21,0.21-0.21h1.61c0.13,0,0.24,0.06,0.3,0.17l1.41,2.36l1.41-2.36 c0.06-0.11,0.18-0.17,0.3-0.17h1.61c0.04,0,0.08,0.01,0.12,0.03c0.09,0.06,0.13,0.19,0.06,0.28l0,0l-2.38,3.64l2.43,3.67 c0.02,0.03,0.03,0.07,0.03,0.12C83.25,14.38,83.16,14.47,83.04,14.47L83.04,14.47L83.04,14.47z\"/%3E %3Cpath class=\"st0\" style=\"opacity:0.9; fill: %23FFFFFF; enable-background: new;\" d=\"M10.5,1.24c-5.11,0-9.25,4.15-9.25,9.25s4.15,9.25,9.25,9.25s9.25-4.15,9.25-9.25 C19.75,5.38,15.61,1.24,10.5,1.24z M14.89,12.77c-1.93,1.93-4.78,2.31-6.7,2.31c-0.7,0-1.41-0.05-2.1-0.16c0,0-1.02-5.64,2.14-8.81 c0.83-0.83,1.95-1.28,3.13-1.28c1.27,0,2.49,0.51,3.39,1.42C16.59,8.09,16.64,11,14.89,12.77z\"/%3E %3Cpath class=\"st1\" style=\"opacity:0.35; enable-background:new;\" d=\"M10.5-0.01C4.7-0.01,0,4.7,0,10.49s4.7,10.5,10.5,10.5S21,16.29,21,10.49C20.99,4.7,16.3-0.01,10.5-0.01z M10.5,19.74c-5.11,0-9.25-4.15-9.25-9.25s4.14-9.26,9.25-9.26s9.25,4.15,9.25,9.25C19.75,15.61,15.61,19.74,10.5,19.74z\"/%3E %3Cpath class=\"st1\" style=\"opacity:0.35; enable-background:new;\" d=\"M14.74,6.25C12.9,4.41,9.98,4.35,8.23,6.1c-3.16,3.17-2.14,8.81-2.14,8.81s5.64,1.02,8.81-2.14 C16.64,11,16.59,8.09,14.74,6.25z M12.47,10.34l-0.91,1.87l-0.9-1.87L8.8,9.43l1.86-0.9l0.9-1.87l0.91,1.87l1.86,0.9L12.47,10.34z\"/%3E %3Cpolygon class=\"st0\" style=\"opacity:0.9; fill: %23FFFFFF; enable-background: new;\" points=\"14.33,9.43 12.47,10.34 11.56,12.21 10.66,10.34 8.8,9.43 10.66,8.53 11.56,6.66 12.47,8.53 \"/%3E%3C/g%3E%3C/svg%3E\\');'\n}};},{}],839:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Lib=_dereq_('../../lib');/**\n * Convert plotly.js 'textposition' to mapbox-gl 'anchor' and 'offset'\n * (with the help of the icon size).\n *\n * @param {string} textpostion : plotly.js textposition value\n * @param {number} iconSize : plotly.js icon size (e.g. marker.size for traces)\n *\n * @return {object}\n * - anchor\n * - offset\n */module.exports=function convertTextOpts(textposition,iconSize){var parts=textposition.split(' ');var vPos=parts[0];var hPos=parts[1];// ballpack values\nvar factor=Lib.isArrayOrTypedArray(iconSize)?Lib.mean(iconSize):iconSize;var xInc=0.5+factor/100;var yInc=1.5+factor/100;var anchorVals=['',''];var offset=[0,0];switch(vPos){case'top':anchorVals[0]='top';offset[1]=-yInc;break;case'bottom':anchorVals[0]='bottom';offset[1]=yInc;break;}switch(hPos){case'left':anchorVals[1]='right';offset[0]=-xInc;break;case'right':anchorVals[1]='left';offset[0]=xInc;break;}// Mapbox text-anchor must be one of:\n// center, left, right, top, bottom,\n// top-left, top-right, bottom-left, bottom-right\nvar anchor;if(anchorVals[0]&&anchorVals[1])anchor=anchorVals.join('-');else if(anchorVals[0])anchor=anchorVals[0];else if(anchorVals[1])anchor=anchorVals[1];else anchor='center';return{anchor:anchor,offset:offset};};},{\"../../lib\":735}],840:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var mapboxgl=_dereq_('mapbox-gl');var Lib=_dereq_('../../lib');var getSubplotCalcData=_dereq_('../../plots/get_data').getSubplotCalcData;var xmlnsNamespaces=_dereq_('../../constants/xmlns_namespaces');var d3=_dereq_('d3');var Drawing=_dereq_('../../components/drawing');var svgTextUtils=_dereq_('../../lib/svg_text_utils');var Mapbox=_dereq_('./mapbox');var MAPBOX='mapbox';var constants=exports.constants=_dereq_('./constants');exports.name=MAPBOX;exports.attr='subplot';exports.idRoot=MAPBOX;exports.idRegex=exports.attrRegex=Lib.counterRegex(MAPBOX);exports.attributes={subplot:{valType:'subplotid',dflt:'mapbox',editType:'calc'}};exports.layoutAttributes=_dereq_('./layout_attributes');exports.supplyLayoutDefaults=_dereq_('./layout_defaults');exports.plot=function plot(gd){var fullLayout=gd._fullLayout;var calcData=gd.calcdata;var mapboxIds=fullLayout._subplots[MAPBOX];if(mapboxgl.version!==constants.requiredVersion){throw new Error(constants.wrongVersionErrorMsg);}var accessToken=findAccessToken(gd,mapboxIds);mapboxgl.accessToken=accessToken;for(var i=0;imaxWidth/2){var multilineAttributions=attributions.split('|').join(' ');attributionText.text(multilineAttributions).attr('data-unformatted',multilineAttributions).call(svgTextUtils.convertToTspans,gd);bBox=Drawing.bBox(attributionText.node());}attributionText.attr('transform','translate(-3, '+(-bBox.height+8)+')');// Draw white rectangle behind text\nattributionGroup.insert('rect','.static-attribution').attr({x:-bBox.width-6,y:-bBox.height-3,width:bBox.width+6,height:bBox.height+3,fill:'rgba(255, 255, 255, 0.75)'});// Scale down if larger than domain\nvar scaleRatio=1;if(bBox.width+6>maxWidth)scaleRatio=maxWidth/(bBox.width+6);var offset=[size.l+size.w*domain.x[1],size.t+size.h*(1-domain.y[0])];attributionGroup.attr('transform','translate('+offset[0]+','+offset[1]+') scale('+scaleRatio+')');}};// N.B. mapbox-gl only allows one accessToken to be set per page:\n// https://github.com/mapbox/mapbox-gl-js/issues/6331\nfunction findAccessToken(gd,mapboxIds){var fullLayout=gd._fullLayout;var context=gd._context;// special case for Mapbox Atlas users\nif(context.mapboxAccessToken==='')return'';var tokensUseful=[];var tokensListed=[];var hasOneSetMapboxStyle=false;var wontWork=false;// Take the first token we find in a mapbox subplot.\n// These default to the context value but may be overridden.\nfor(var i=0;i1){Lib.warn(constants.multipleTokensErrorMsg);}return tokensUseful[0];}else{if(tokensListed.length){Lib.log(['Listed mapbox access token(s)',tokensListed.join(','),'but did not use a Mapbox map style, ignoring token(s).'].join(' '));}return'';}}function isMapboxStyle(s){return typeof s==='string'&&(constants.styleValuesMapbox.indexOf(s)!==-1||s.indexOf('mapbox://')===0);}exports.updateFx=function(gd){var fullLayout=gd._fullLayout;var subplotIds=fullLayout._subplots[MAPBOX];for(var i=0;i0){for(var i=0;i0;}function convertOpts(opts){var layout={};var paint={};switch(opts.type){case'circle':Lib.extendFlat(paint,{'circle-radius':opts.circle.radius,'circle-color':opts.color,'circle-opacity':opts.opacity});break;case'line':Lib.extendFlat(paint,{'line-width':opts.line.width,'line-color':opts.color,'line-opacity':opts.opacity,'line-dasharray':opts.line.dash});break;case'fill':Lib.extendFlat(paint,{'fill-color':opts.color,'fill-outline-color':opts.fill.outlinecolor,'fill-opacity':opts.opacity// no way to pass specify outline width at the moment\n});break;case'symbol':var symbol=opts.symbol;var textOpts=convertTextOpts(symbol.textposition,symbol.iconsize);Lib.extendFlat(layout,{'icon-image':symbol.icon+'-15','icon-size':symbol.iconsize/10,'text-field':symbol.text,'text-size':symbol.textfont.size,'text-anchor':textOpts.anchor,'text-offset':textOpts.offset,'symbol-placement':symbol.placement// TODO font family\n// 'text-font': symbol.textfont.family.split(', '),\n});Lib.extendFlat(paint,{'icon-color':opts.color,'text-color':symbol.textfont.color,'text-opacity':opts.opacity});break;case'raster':Lib.extendFlat(paint,{'raster-fade-duration':0,'raster-opacity':opts.opacity});break;}return{layout:layout,paint:paint};}function convertSourceOpts(opts){var sourceType=opts.sourcetype;var source=opts.source;var sourceOpts={type:sourceType};var field;if(sourceType==='geojson'){field='data';}else if(sourceType==='vector'){field=typeof source==='string'?'url':'tiles';}else if(sourceType==='raster'){field='tiles';sourceOpts.tileSize=256;}else if(sourceType==='image'){field='url';sourceOpts.coordinates=opts.coordinates;}sourceOpts[field]=source;if(opts.sourceattribution){sourceOpts.attribution=sanitizeHTML(opts.sourceattribution);}return sourceOpts;}module.exports=function createMapboxLayer(subplot,index,opts){var mapboxLayer=new MapboxLayer(subplot,index);mapboxLayer.update(opts);return mapboxLayer;};},{\"../../lib\":735,\"../../lib/svg_text_utils\":759,\"./constants\":838,\"./convert_text_opts\":839}],842:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Lib=_dereq_('../../lib');var defaultLine=_dereq_('../../components/color').defaultLine;var domainAttrs=_dereq_('../domain').attributes;var fontAttrs=_dereq_('../font_attributes');var textposition=_dereq_('../../traces/scatter/attributes').textposition;var overrideAll=_dereq_('../../plot_api/edit_types').overrideAll;var templatedArray=_dereq_('../../plot_api/plot_template').templatedArray;var constants=_dereq_('./constants');var fontAttr=fontAttrs({});fontAttr.family.dflt='Open Sans Regular, Arial Unicode MS Regular';var attrs=module.exports=overrideAll({_arrayAttrRegexps:[Lib.counterRegex('mapbox','.layers',true)],domain:domainAttrs({name:'mapbox'}),accesstoken:{valType:'string',noBlank:true,strict:true},style:{valType:'any',values:constants.styleValuesMapbox.concat(constants.styleValuesNonMapbox),dflt:constants.styleValueDflt},center:{lon:{valType:'number',dflt:0},lat:{valType:'number',dflt:0}},zoom:{valType:'number',dflt:1},bearing:{valType:'number',dflt:0},pitch:{valType:'number',dflt:0},layers:templatedArray('layer',{visible:{valType:'boolean',dflt:true},sourcetype:{valType:'enumerated',values:['geojson','vector','raster','image'],dflt:'geojson'},source:{valType:'any'},sourcelayer:{valType:'string',dflt:''},sourceattribution:{valType:'string'},type:{valType:'enumerated',values:['circle','line','fill','symbol','raster'],dflt:'circle'},coordinates:{valType:'any'},// attributes shared between all types\nbelow:{valType:'string'},color:{valType:'color',dflt:defaultLine},opacity:{valType:'number',min:0,max:1,dflt:1},minzoom:{valType:'number',min:0,max:24,dflt:0},maxzoom:{valType:'number',min:0,max:24,dflt:24},// type-specific style attributes\ncircle:{radius:{valType:'number',dflt:15}},line:{width:{valType:'number',dflt:2},dash:{valType:'data_array'}},fill:{outlinecolor:{valType:'color',dflt:defaultLine}},symbol:{icon:{valType:'string',dflt:'marker'},iconsize:{valType:'number',dflt:10},text:{valType:'string',dflt:''},placement:{valType:'enumerated',values:['point','line','line-center'],dflt:'point'},textfont:fontAttr,textposition:Lib.extendFlat({},textposition,{arrayOk:false})}})},'plot','from-root');// set uirevision outside of overrideAll so it can be `editType: 'none'`\nattrs.uirevision={valType:'any',editType:'none'};},{\"../../components/color\":602,\"../../lib\":735,\"../../plot_api/edit_types\":766,\"../../plot_api/plot_template\":773,\"../../traces/scatter/attributes\":1140,\"../domain\":810,\"../font_attributes\":811,\"./constants\":838}],843:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Lib=_dereq_('../../lib');var handleSubplotDefaults=_dereq_('../subplot_defaults');var handleArrayContainerDefaults=_dereq_('../array_container_defaults');var layoutAttributes=_dereq_('./layout_attributes');module.exports=function supplyLayoutDefaults(layoutIn,layoutOut,fullData){handleSubplotDefaults(layoutIn,layoutOut,fullData,{type:'mapbox',attributes:layoutAttributes,handleDefaults:handleDefaults,partition:'y',accessToken:layoutOut._mapboxAccessToken});};function handleDefaults(containerIn,containerOut,coerce,opts){coerce('accesstoken',opts.accessToken);coerce('style');coerce('center.lon');coerce('center.lat');coerce('zoom');coerce('bearing');coerce('pitch');handleArrayContainerDefaults(containerIn,containerOut,{name:'layers',handleItemDefaults:handleLayerDefaults});// copy ref to input container to update 'center' and 'zoom' on map move\ncontainerOut._input=containerIn;}function handleLayerDefaults(layerIn,layerOut){function coerce(attr,dflt){return Lib.coerce(layerIn,layerOut,layoutAttributes.layers,attr,dflt);}var visible=coerce('visible');if(visible){var sourceType=coerce('sourcetype');var mustBeRasterLayer=sourceType==='raster'||sourceType==='image';coerce('source');coerce('sourceattribution');if(sourceType==='vector'){coerce('sourcelayer');}if(sourceType==='image'){coerce('coordinates');}var typeDflt;if(mustBeRasterLayer)typeDflt='raster';var type=coerce('type',typeDflt);if(mustBeRasterLayer&&type!=='raster'){type=layerOut.type='raster';Lib.log('Source types *raster* and *image* must drawn *raster* layer type.');}coerce('below');coerce('color');coerce('opacity');coerce('minzoom');coerce('maxzoom');if(type==='circle'){coerce('circle.radius');}if(type==='line'){coerce('line.width');coerce('line.dash');}if(type==='fill'){coerce('fill.outlinecolor');}if(type==='symbol'){coerce('symbol.icon');coerce('symbol.iconsize');coerce('symbol.text');Lib.coerceFont(coerce,'symbol.textfont');coerce('symbol.textposition');coerce('symbol.placement');}}}},{\"../../lib\":735,\"../array_container_defaults\":779,\"../subplot_defaults\":860,\"./layout_attributes\":842}],844:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var mapboxgl=_dereq_('mapbox-gl');var Lib=_dereq_('../../lib');var geoUtils=_dereq_('../../lib/geo_location_utils');var Registry=_dereq_('../../registry');var Axes=_dereq_('../cartesian/axes');var dragElement=_dereq_('../../components/dragelement');var Fx=_dereq_('../../components/fx');var dragHelpers=_dereq_('../../components/dragelement/helpers');var rectMode=dragHelpers.rectMode;var drawMode=dragHelpers.drawMode;var selectMode=dragHelpers.selectMode;var prepSelect=_dereq_('../cartesian/select').prepSelect;var clearSelect=_dereq_('../cartesian/select').clearSelect;var clearSelectionsCache=_dereq_('../cartesian/select').clearSelectionsCache;var selectOnClick=_dereq_('../cartesian/select').selectOnClick;var constants=_dereq_('./constants');var createMapboxLayer=_dereq_('./layers');function Mapbox(gd,id){this.id=id;this.gd=gd;var fullLayout=gd._fullLayout;var context=gd._context;this.container=fullLayout._glcontainer.node();this.isStatic=context.staticPlot;// unique id for this Mapbox instance\nthis.uid=fullLayout._uid+'-'+this.id;// create framework on instantiation for a smoother first plot call\nthis.div=null;this.xaxis=null;this.yaxis=null;this.createFramework(fullLayout);// state variables used to infer how and what to update\nthis.map=null;this.accessToken=null;this.styleObj=null;this.traceHash={};this.layerList=[];this.belowLookup={};this.dragging=false;this.wheeling=false;}var proto=Mapbox.prototype;proto.plot=function(calcData,fullLayout,promises){var self=this;var opts=fullLayout[self.id];// remove map and create a new map if access token has change\nif(self.map&&opts.accesstoken!==self.accessToken){self.map.remove();self.map=null;self.styleObj=null;self.traceHash={};self.layerList=[];}var promise;if(!self.map){promise=new Promise(function(resolve,reject){self.createMap(calcData,fullLayout,resolve,reject);});}else{promise=new Promise(function(resolve,reject){self.updateMap(calcData,fullLayout,resolve,reject);});}promises.push(promise);};proto.createMap=function(calcData,fullLayout,resolve,reject){var self=this;var opts=fullLayout[self.id];// store style id and URL or object\nvar styleObj=self.styleObj=getStyleObj(opts.style);// store access token associated with this map\nself.accessToken=opts.accesstoken;// create the map!\nvar map=self.map=new mapboxgl.Map({container:self.div,style:styleObj.style,center:convertCenter(opts.center),zoom:opts.zoom,bearing:opts.bearing,pitch:opts.pitch,interactive:!self.isStatic,preserveDrawingBuffer:self.isStatic,doubleClickZoom:false,boxZoom:false,attributionControl:false}).addControl(new mapboxgl.AttributionControl({compact:true}));// make sure canvas does not inherit left and top css\nmap._canvas.style.left='0px';map._canvas.style.top='0px';self.rejectOnError(reject);if(!self.isStatic){self.initFx(calcData,fullLayout);}var promises=[];promises.push(new Promise(function(resolve){map.once('load',resolve);}));promises=promises.concat(geoUtils.fetchTraceGeoData(calcData));Promise.all(promises).then(function(){self.fillBelowLookup(calcData,fullLayout);self.updateData(calcData);self.updateLayout(fullLayout);self.resolveOnRender(resolve);}).catch(reject);};proto.updateMap=function(calcData,fullLayout,resolve,reject){var self=this;var map=self.map;var opts=fullLayout[this.id];self.rejectOnError(reject);var promises=[];var styleObj=getStyleObj(opts.style);if(JSON.stringify(self.styleObj)!==JSON.stringify(styleObj)){self.styleObj=styleObj;map.setStyle(styleObj.style);// need to rebuild trace layers on reload\n// to avoid 'lost event' errors\nself.traceHash={};promises.push(new Promise(function(resolve){map.once('styledata',resolve);}));}promises=promises.concat(geoUtils.fetchTraceGeoData(calcData));Promise.all(promises).then(function(){self.fillBelowLookup(calcData,fullLayout);self.updateData(calcData);self.updateLayout(fullLayout);self.resolveOnRender(resolve);}).catch(reject);};proto.fillBelowLookup=function(calcData,fullLayout){var opts=fullLayout[this.id];var layers=opts.layers;var i,val;var belowLookup=this.belowLookup={};var hasTraceAtTop=false;for(i=0;i1){for(i=0;i-1){selectOnClick(evt.originalEvent,gd,[self.xaxis],[self.yaxis],self.id,dragOptions);}if(clickMode.indexOf('event')>-1){// TODO: this does not support right-click. If we want to support it, we\n// would likely need to change mapbox to use dragElement instead of straight\n// mapbox event binding. Or perhaps better, make a simple wrapper with the\n// right mousedown, mousemove, and mouseup handlers just for a left/right click\n// pie would use this too.\nFx.click(gd,evt.originalEvent);}};};};proto.updateFx=function(fullLayout){var self=this;var map=self.map;var gd=self.gd;if(self.isStatic)return;function invert(pxpy){var obj=self.map.unproject(pxpy);return[obj.lng,obj.lat];}var dragMode=fullLayout.dragmode;var fillRangeItems;if(rectMode(dragMode)){fillRangeItems=function(eventData,poly){var ranges=eventData.range={};ranges[self.id]=[invert([poly.xmin,poly.ymin]),invert([poly.xmax,poly.ymax])];};}else{fillRangeItems=function(eventData,poly,pts){var dataPts=eventData.lassoPoints={};dataPts[self.id]=pts.filtered.map(invert);};}// Note: dragOptions is needed to be declared for all dragmodes because\n// it's the object that holds persistent selection state.\n// Merge old dragOptions with new to keep possibly initialized\n// persistent selection state.\nvar oldDragOptions=self.dragOptions;self.dragOptions=Lib.extendDeep(oldDragOptions||{},{dragmode:fullLayout.dragmode,element:self.div,gd:gd,plotinfo:{id:self.id,domain:fullLayout[self.id].domain,xaxis:self.xaxis,yaxis:self.yaxis,fillRangeItems:fillRangeItems},xaxes:[self.xaxis],yaxes:[self.yaxis],subplot:self.id});// Unregister the old handler before potentially registering\n// a new one. Otherwise multiple click handlers might\n// be registered resulting in unwanted behavior.\nmap.off('click',self.onClickInPanHandler);if(selectMode(dragMode)||drawMode(dragMode)){map.dragPan.disable();map.on('zoomstart',self.clearSelect);self.dragOptions.prepFn=function(e,startX,startY){prepSelect(e,startX,startY,self.dragOptions,dragMode);};dragElement.init(self.dragOptions);}else{map.dragPan.enable();map.off('zoomstart',self.clearSelect);self.div.onmousedown=null;// TODO: this does not support right-click. If we want to support it, we\n// would likely need to change mapbox to use dragElement instead of straight\n// mapbox event binding. Or perhaps better, make a simple wrapper with the\n// right mousedown, mousemove, and mouseup handlers just for a left/right click\n// pie would use this too.\nself.onClickInPanHandler=self.onClickInPanFn(self.dragOptions);map.on('click',self.onClickInPanHandler);}};proto.updateFramework=function(fullLayout){var domain=fullLayout[this.id].domain;var size=fullLayout._size;var style=this.div.style;style.width=size.w*(domain.x[1]-domain.x[0])+'px';style.height=size.h*(domain.y[1]-domain.y[0])+'px';style.left=size.l+domain.x[0]*size.w+'px';style.top=size.t+(1-domain.y[1])*size.h+'px';this.xaxis._offset=size.l+domain.x[0]*size.w;this.xaxis._length=size.w*(domain.x[1]-domain.x[0]);this.yaxis._offset=size.t+(1-domain.y[1])*size.h;this.yaxis._length=size.h*(domain.y[1]-domain.y[0]);};proto.updateLayers=function(fullLayout){var opts=fullLayout[this.id];var layers=opts.layers;var layerList=this.layerList;var i;// if the layer arrays don't match,\n// don't try to be smart,\n// delete them all, and start all over.\nif(layers.length!==layerList.length){for(i=0;i=fullLayout.width-20){// Align the text at the left\nattrs['text-anchor']='start';attrs.x=5;}else{// Align the text at the right\nattrs['text-anchor']='end';attrs.x=fullLayout._paper.attr('width')-7;}linkContainer.attr(attrs);var toolspan=linkContainer.select('.js-link-to-tool');var spacespan=linkContainer.select('.js-link-spacer');var sourcespan=linkContainer.select('.js-sourcelinks');if(gd._context.showSources)gd._context.showSources(gd);// 'view in plotly' link for embedded plots\nif(gd._context.showLink)positionPlayWithData(gd,toolspan);// separator if we have both sources and tool link\nspacespan.text(toolspan.text()&&sourcespan.text()?' - ':'');};// note that now this function is only adding the brand in\n// iframes and 3rd-party apps\nfunction positionPlayWithData(gd,container){container.text('');var link=container.append('a').attr({'xlink:xlink:href':'#','class':'link--impt link--embedview','font-weight':'bold'}).text(gd._context.linkText+' '+String.fromCharCode(187));if(gd._context.sendData){link.on('click',function(){plots.sendDataToCloud(gd);});}else{var path=window.location.pathname.split('/');var query=window.location.search;link.attr({'xlink:xlink:show':'new','xlink:xlink:href':'/'+path[2].split('.')[0]+'/'+path[1]+query});}}plots.sendDataToCloud=function(gd){var baseUrl=(window.PLOTLYENV||{}).BASE_URL||gd._context.plotlyServerURL;if(!baseUrl)return;gd.emit('plotly_beforeexport');var hiddenformDiv=d3.select(gd).append('div').attr('id','hiddenform').style('display','none');var hiddenform=hiddenformDiv.append('form').attr({action:baseUrl+'/external',method:'post',target:'_blank'});var hiddenformInput=hiddenform.append('input').attr({type:'text',name:'data'});hiddenformInput.node().value=plots.graphJson(gd,false,'keepdata');hiddenform.node().submit();hiddenformDiv.remove();gd.emit('plotly_afterexport');return false;};var d3FormatKeys=['days','shortDays','months','shortMonths','periods','dateTime','date','time','decimal','thousands','grouping','currency'];var extraFormatKeys=['year','month','dayMonth','dayMonthYear'];/*\n * Fill in default values\n * @param {DOM element} gd\n * @param {object} opts\n * @param {boolean} opts.skipUpdateCalc: normally if the existing gd.calcdata looks\n * compatible with the new gd._fullData we finish by linking the new _fullData traces\n * to the old gd.calcdata, so it's correctly set if we're not going to recalc. But also,\n * if there are calcTransforms on the trace, we first remap data arrays from the old full\n * trace into the new one. Use skipUpdateCalc to defer this (needed by Plotly.react)\n *\n * gd.data, gd.layout:\n * are precisely what the user specified (except as modified by cleanData/cleanLayout),\n * these fields shouldn't be modified (except for filling in some auto values)\n * nor used directly after the supply defaults step.\n *\n * gd._fullData, gd._fullLayout:\n * are complete descriptions of how to draw the plot,\n * use these fields in all required computations.\n *\n * gd._fullLayout._modules\n * is a list of all the trace modules required to draw the plot.\n *\n * gd._fullLayout._visibleModules\n * subset of _modules, a list of modules corresponding to visible:true traces.\n *\n * gd._fullLayout._basePlotModules\n * is a list of all the plot modules required to draw the plot.\n *\n * gd._fullLayout._transformModules\n * is a list of all the transform modules invoked.\n *\n */plots.supplyDefaults=function(gd,opts){var skipUpdateCalc=opts&&opts.skipUpdateCalc;var oldFullLayout=gd._fullLayout||{};if(oldFullLayout._skipDefaults){delete oldFullLayout._skipDefaults;return;}var newFullLayout=gd._fullLayout={};var newLayout=gd.layout||{};var oldFullData=gd._fullData||[];var newFullData=gd._fullData=[];var newData=gd.data||[];var oldCalcdata=gd.calcdata||[];var context=gd._context||{};var i;// Create all the storage space for frames, but only if doesn't already exist\nif(!gd._transitionData)plots.createTransitionData(gd);// So we only need to do this once (and since we have gd here)\n// get the translated placeholder titles.\n// These ones get used as default values so need to be known at supplyDefaults\n// others keep their blank defaults but render the placeholder as desired later\n// TODO: make these work the same way, only inserting the placeholder text at draw time?\n// The challenge is that this has slightly different behavior right now in editable mode:\n// using the placeholder as default makes this text permanently (but lightly) visible,\n// but explicit '' for these titles gives you a placeholder that's hidden until you mouse\n// over it - so you're not distracted by it if you really don't want a title, but if you do\n// and you're new to plotly you may not be able to find it.\n// When editable=false the two behave the same, no title is drawn.\nnewFullLayout._dfltTitle={plot:_(gd,'Click to enter Plot title'),x:_(gd,'Click to enter X axis title'),y:_(gd,'Click to enter Y axis title'),colorbar:_(gd,'Click to enter Colorscale title'),annotation:_(gd,'new text')};newFullLayout._traceWord=_(gd,'trace');var formatObj=getFormatObj(gd,d3FormatKeys);// stash the token from context so mapbox subplots can use it as default\nnewFullLayout._mapboxAccessToken=context.mapboxAccessToken;// first fill in what we can of layout without looking at data\n// because fullData needs a few things from layout\nif(oldFullLayout._initialAutoSizeIsDone){// coerce the updated layout while preserving width and height\nvar oldWidth=oldFullLayout.width;var oldHeight=oldFullLayout.height;plots.supplyLayoutGlobalDefaults(newLayout,newFullLayout,formatObj);if(!newLayout.width)newFullLayout.width=oldWidth;if(!newLayout.height)newFullLayout.height=oldHeight;plots.sanitizeMargins(newFullLayout);}else{// coerce the updated layout and autosize if needed\nplots.supplyLayoutGlobalDefaults(newLayout,newFullLayout,formatObj);var missingWidthOrHeight=!newLayout.width||!newLayout.height;var autosize=newFullLayout.autosize;var autosizable=context.autosizable;var initialAutoSize=missingWidthOrHeight&&(autosize||autosizable);if(initialAutoSize)plots.plotAutoSize(gd,newLayout,newFullLayout);else if(missingWidthOrHeight)plots.sanitizeMargins(newFullLayout);// for backwards-compatibility with Plotly v1.x.x\nif(!autosize&&missingWidthOrHeight){newLayout.width=newFullLayout.width;newLayout.height=newFullLayout.height;}}newFullLayout._d3locale=getFormatter(formatObj,newFullLayout.separators);newFullLayout._extraFormat=getFormatObj(gd,extraFormatKeys);newFullLayout._initialAutoSizeIsDone=true;// keep track of how many traces are inputted\nnewFullLayout._dataLength=newData.length;// clear the lists of trace and baseplot modules, and subplots\nnewFullLayout._modules=[];newFullLayout._visibleModules=[];newFullLayout._basePlotModules=[];var subplots=newFullLayout._subplots=emptySubplotLists();// initialize axis and subplot hash objects for splom-generated grids\nvar splomAxes=newFullLayout._splomAxes={x:{},y:{}};var splomSubplots=newFullLayout._splomSubplots={};// initialize splom grid defaults\nnewFullLayout._splomGridDflt={};// for stacked area traces to share config across traces\nnewFullLayout._scatterStackOpts={};// for the first scatter trace on each subplot (so it knows tonext->tozero)\nnewFullLayout._firstScatter={};// for grouped bar/box/violin trace to share config across traces\nnewFullLayout._alignmentOpts={};// track color axes referenced in the data\nnewFullLayout._colorAxes={};// for traces to request a default rangeslider on their x axes\n// eg set `_requestRangeslider.x2 = true` for xaxis2\nnewFullLayout._requestRangeslider={};// pull uids from old data to use as new defaults\nnewFullLayout._traceUids=getTraceUids(oldFullData,newData);// then do the data\nnewFullLayout._globalTransforms=(gd._context||{}).globalTransforms;plots.supplyDataDefaults(newData,newFullData,newLayout,newFullLayout);// redo grid size defaults with info about splom x/y axes,\n// and fill in generated cartesian axes and subplots\nvar splomXa=Object.keys(splomAxes.x);var splomYa=Object.keys(splomAxes.y);if(splomXa.length>1&&splomYa.length>1){Registry.getComponentMethod('grid','sizeDefaults')(newLayout,newFullLayout);for(i=0;i15&&splomYa.length>15&&newFullLayout.shapes.length===0&&newFullLayout.images.length===0;// TODO remove in v2.0.0\n// add has-plot-type refs to fullLayout for backward compatibility\nnewFullLayout._hasCartesian=newFullLayout._has('cartesian');newFullLayout._hasGeo=newFullLayout._has('geo');newFullLayout._hasGL3D=newFullLayout._has('gl3d');newFullLayout._hasGL2D=newFullLayout._has('gl2d');newFullLayout._hasTernary=newFullLayout._has('ternary');newFullLayout._hasPie=newFullLayout._has('pie');// relink / initialize subplot axis objects\nplots.linkSubplots(newFullData,newFullLayout,oldFullData,oldFullLayout);// clean subplots and other artifacts from previous plot calls\nplots.cleanPlot(newFullData,newFullLayout,oldFullData,oldFullLayout);// clear selection outline until we implement persistent selection,\n// don't clear them though when drag handlers (e.g. listening to\n// `plotly_selecting`) update the graph.\n// we should try to come up with a better solution when implementing\n// https://github.com/plotly/plotly.js/issues/1851\nif(oldFullLayout._zoomlayer&&!gd._dragging){clearSelect({// mock old gd\n_fullLayout:oldFullLayout});}// fill in meta helpers\nfillMetaTextHelpers(newFullData,newFullLayout);// relink functions and _ attributes to promote consistency between plots\nrelinkPrivateKeys(newFullLayout,oldFullLayout);// colorscale crossTraceDefaults needs newFullLayout with relinked keys\nRegistry.getComponentMethod('colorscale','crossTraceDefaults')(newFullData,newFullLayout);// For persisting GUI-driven changes in layout\n// _preGUI and _tracePreGUI were already copied over in relinkPrivateKeys\nif(!newFullLayout._preGUI)newFullLayout._preGUI={};// track trace GUI changes by uid rather than by trace index\nif(!newFullLayout._tracePreGUI)newFullLayout._tracePreGUI={};var tracePreGUI=newFullLayout._tracePreGUI;var uids={};var uid;for(uid in tracePreGUI)uids[uid]='old';for(i=0;i0){var factor=1-2*frameMargins;newWidth=Math.round(factor*newWidth);newHeight=Math.round(factor*newHeight);}}var minWidth=plots.layoutAttributes.width.min;var minHeight=plots.layoutAttributes.height.min;if(newWidth1;var heightHasChanged=!layout.height&&Math.abs(fullLayout.height-newHeight)>1;if(heightHasChanged||widthHasChanged){if(widthHasChanged)fullLayout.width=newWidth;if(heightHasChanged)fullLayout.height=newHeight;}// cache initial autosize value, used in relayout when\n// width or height values are set to null\nif(!gd._initialAutoSize){gd._initialAutoSize={width:newWidth,height:newHeight};}plots.sanitizeMargins(fullLayout);};plots.supplyLayoutModuleDefaults=function(layoutIn,layoutOut,fullData,transitionData){var componentsRegistry=Registry.componentsRegistry;var basePlotModules=layoutOut._basePlotModules;var component,i,_module;var Cartesian=Registry.subplotsRegistry.cartesian;// check if any components need to add more base plot modules\n// that weren't captured by traces\nfor(component in componentsRegistry){_module=componentsRegistry[component];if(_module.includeBasePlot){_module.includeBasePlot(layoutIn,layoutOut);}}// make sure we *at least* have some cartesian axes\nif(!basePlotModules.length){basePlotModules.push(Cartesian);}// ensure all cartesian axes have at least one subplot\nif(layoutOut._has('cartesian')){Registry.getComponentMethod('grid','contentDefaults')(layoutIn,layoutOut);Cartesian.finalizeSubplots(layoutIn,layoutOut);}// sort subplot lists\nfor(var subplotType in layoutOut._subplots){layoutOut._subplots[subplotType].sort(Lib.subplotSort);}// base plot module layout defaults\nfor(i=0;i 0\n// as width >= 10 by supplyDefaults\n// similarly for margin.t + margin.b\nif(plotWidth<0){correction=(width-1)/(margin.l+margin.r);margin.l=Math.floor(correction*margin.l);margin.r=Math.floor(correction*margin.r);}if(plotHeight<0){correction=(height-1)/(margin.t+margin.b);margin.t=Math.floor(correction*margin.t);margin.b=Math.floor(correction*margin.b);}};plots.clearAutoMarginIds=function(gd){gd._fullLayout._pushmarginIds={};};plots.allowAutoMargin=function(gd,id){gd._fullLayout._pushmarginIds[id]=1;};function initMargins(fullLayout){var margin=fullLayout.margin;if(!fullLayout._size){var gs=fullLayout._size={l:Math.round(margin.l),r:Math.round(margin.r),t:Math.round(margin.t),b:Math.round(margin.b),p:Math.round(margin.pad)};gs.w=Math.round(fullLayout.width)-gs.l-gs.r;gs.h=Math.round(fullLayout.height)-gs.t-gs.b;}if(!fullLayout._pushmargin)fullLayout._pushmargin={};if(!fullLayout._pushmarginIds)fullLayout._pushmarginIds={};}/**\n * autoMargin: called by components that may need to expand the margins to\n * be rendered on-plot.\n *\n * @param {DOM element} gd\n * @param {string} id - an identifier unique (within this plot) to this object,\n * so we can remove a previous margin expansion from the same object.\n * @param {object} o - the margin requirements of this object, or omit to delete\n * this entry (like if it's hidden). Keys are:\n * x, y: plot fraction of the anchor point.\n * xl, xr, yt, yb: if the object has an extent defined in plot fraction,\n * you can specify both edges as plot fractions in each dimension\n * l, r, t, b: the pixels to pad past the plot fraction x[l|r] and y[t|b]\n * pad: extra pixels to add in all directions, default 12 (why?)\n */plots.autoMargin=function(gd,id,o){var fullLayout=gd._fullLayout;var pushMargin=fullLayout._pushmargin;var pushMarginIds=fullLayout._pushmarginIds;if(fullLayout.margin.autoexpand!==false){if(!o){delete pushMargin[id];delete pushMarginIds[id];}else{var pad=o.pad;if(pad===undefined){var margin=fullLayout.margin;// if no explicit pad is given, use 12px unless there's a\n// specified margin that's smaller than that\npad=Math.min(12,margin.l,margin.r,margin.t,margin.b);}// if the item is too big, just give it enough automargin to\n// make sure you can still grab it and bring it back\nif(o.l+o.r>fullLayout.width*0.5){Lib.log('Margin push',id,'is too big in x, dropping');o.l=o.r=0;}if(o.b+o.t>fullLayout.height*0.5){Lib.log('Margin push',id,'is too big in y, dropping');o.b=o.t=0;}var xl=o.xl!==undefined?o.xl:o.x;var xr=o.xr!==undefined?o.xr:o.x;var yt=o.yt!==undefined?o.yt:o.y;var yb=o.yb!==undefined?o.yb:o.y;pushMargin[id]={l:{val:xl,size:o.l+pad},r:{val:xr,size:o.r+pad},b:{val:yb,size:o.b+pad},t:{val:yt,size:o.t+pad}};pushMarginIds[id]=1;}if(!fullLayout._replotting){return plots.doAutoMargin(gd);}}};plots.doAutoMargin=function(gd){var fullLayout=gd._fullLayout;if(!fullLayout._size)fullLayout._size={};initMargins(fullLayout);var gs=fullLayout._size;var margin=fullLayout.margin;var oldMargins=Lib.extendFlat({},gs);// adjust margins for outside components\n// fullLayout.margin is the requested margin,\n// fullLayout._size has margins and plotsize after adjustment\nvar ml=margin.l;var mr=margin.r;var mt=margin.t;var mb=margin.b;var width=fullLayout.width;var height=fullLayout.height;var pushMargin=fullLayout._pushmargin;var pushMarginIds=fullLayout._pushmarginIds;if(fullLayout.margin.autoexpand!==false){for(var k in pushMargin){if(!pushMarginIds[k])delete pushMargin[k];}// fill in the requested margins\npushMargin.base={l:{val:0,size:ml},r:{val:1,size:mr},t:{val:1,size:mt},b:{val:0,size:mb}};// now cycle through all the combinations of l and r\n// (and t and b) to find the required margins\nfor(var k1 in pushMargin){var pushleft=pushMargin[k1].l||{};var pushbottom=pushMargin[k1].b||{};var fl=pushleft.val;var pl=pushleft.size;var fb=pushbottom.val;var pb=pushbottom.size;for(var k2 in pushMargin){if(isNumeric(pl)&&pushMargin[k2].r){var fr=pushMargin[k2].r.val;var pr=pushMargin[k2].r.size;if(fr>fl){var newL=(pl*fr+(pr-width)*fl)/(fr-fl);var newR=(pr*(1-fl)+(pl-width)*(1-fr))/(fr-fl);if(newL>=0&&newR>=0&&width-(newL+newR)>0&&newL+newR>ml+mr){ml=newL;mr=newR;}}}if(isNumeric(pb)&&pushMargin[k2].t){var ft=pushMargin[k2].t.val;var pt=pushMargin[k2].t.size;if(ft>fb){var newB=(pb*ft+(pt-height)*fb)/(ft-fb);var newT=(pt*(1-fb)+(pb-height)*(1-ft))/(ft-fb);if(newB>=0&&newT>=0&&height-(newT+newB)>0&&newB+newT>mb+mt){mb=newB;mt=newT;}}}}}}gs.l=Math.round(ml);gs.r=Math.round(mr);gs.t=Math.round(mt);gs.b=Math.round(mb);gs.p=Math.round(margin.pad);gs.w=Math.round(width)-gs.l-gs.r;gs.h=Math.round(height)-gs.t-gs.b;// if things changed and we're not already redrawing, trigger a redraw\nif(!fullLayout._replotting&&plots.didMarginChange(oldMargins,gs)){if('_redrawFromAutoMarginCount'in fullLayout){fullLayout._redrawFromAutoMarginCount++;}else{fullLayout._redrawFromAutoMarginCount=1;}// Always allow at least one redraw and give each margin-push\n// call 3 loops to converge. Of course, for most cases this way too many,\n// but let's keep things on the safe side until we fix our\n// auto-margin pipeline problems:\n// https://github.com/plotly/plotly.js/issues/2704\nvar maxNumberOfRedraws=3*(1+Object.keys(pushMarginIds).length);if(fullLayout._redrawFromAutoMarginCount1){return true;}}return false;};/**\n * JSONify the graph data and layout\n *\n * This function needs to recurse because some src can be inside\n * sub-objects.\n *\n * It also strips out functions and private (starts with _) elements.\n * Therefore, we can add temporary things to data and layout that don't\n * get saved.\n *\n * @param gd The graphDiv\n * @param {Boolean} dataonly If true, don't return layout.\n * @param {'keepref'|'keepdata'|'keepall'} [mode='keepref'] Filter what's kept\n * keepref: remove data for which there's a src present\n * eg if there's xsrc present (and xsrc is well-formed,\n * ie has : and some chars before it), strip out x\n * keepdata: remove all src tags, don't remove the data itself\n * keepall: keep data and src\n * @param {String} output If you specify 'object', the result will not be stringified\n * @param {Boolean} useDefaults If truthy, use _fullLayout and _fullData\n * @param {Boolean} includeConfig If truthy, include _context\n * @returns {Object|String}\n */plots.graphJson=function(gd,dataonly,mode,output,useDefaults,includeConfig){// if the defaults aren't supplied yet, we need to do that...\nif(useDefaults&&dataonly&&!gd._fullData||useDefaults&&!dataonly&&!gd._fullLayout){plots.supplyDefaults(gd);}var data=useDefaults?gd._fullData:gd.data;var layout=useDefaults?gd._fullLayout:gd.layout;var frames=(gd._transitionData||{})._frames;function stripObj(d,keepFunction){if(typeof d==='function'){return keepFunction?'_function_':null;}if(Lib.isPlainObject(d)){var o={};var src;Object.keys(d).sort().forEach(function(v){// remove private elements and functions\n// _ is for private, [ is a mistake ie [object Object]\nif(['_','['].indexOf(v.charAt(0))!==-1)return;// if a function, add if necessary then move on\nif(typeof d[v]==='function'){if(keepFunction)o[v]='_function';return;}// look for src/data matches and remove the appropriate one\nif(mode==='keepdata'){// keepdata: remove all ...src tags\nif(v.substr(v.length-3)==='src'){return;}}else if(mode==='keepstream'){// keep sourced data if it's being streamed.\n// similar to keepref, but if the 'stream' object exists\n// in a trace, we will keep the data array.\nsrc=d[v+'src'];if(typeof src==='string'&&src.indexOf(':')>0){if(!Lib.isPlainObject(d.stream)){return;}}}else if(mode!=='keepall'){// keepref: remove sourced data but only\n// if the source tag is well-formed\nsrc=d[v+'src'];if(typeof src==='string'&&src.indexOf(':')>0){return;}}// OK, we're including this... recurse into it\no[v]=stripObj(d[v],keepFunction);});return o;}if(Array.isArray(d)){return d.map(function(x){return stripObj(x,keepFunction);});}if(Lib.isTypedArray(d)){return Lib.simpleMap(d,Lib.identity);}// convert native dates to date strings...\n// mostly for external users exporting to plotly\nif(Lib.isJSDate(d))return Lib.ms2DateTimeLocal(+d);return d;}var obj={data:(data||[]).map(function(v){var d=stripObj(v);// fit has some little arrays in it that don't contain data,\n// just fit params and meta\nif(dataonly){delete d.fit;}return d;})};if(!dataonly){obj.layout=stripObj(layout);}if(gd.framework&&gd.framework.isPolar)obj=gd.framework.getConfig();if(frames)obj.frames=stripObj(frames);if(includeConfig)obj.config=stripObj(gd._context,true);return output==='object'?obj:JSON.stringify(obj);};/**\n * Modify a keyframe using a list of operations:\n *\n * @param {array of objects} operations\n * Sequence of operations to be performed on the keyframes\n */plots.modifyFrames=function(gd,operations){var i,op,frame;var _frames=gd._transitionData._frames;var _frameHash=gd._transitionData._frameHash;for(i=0;i frame object. addFrames/\n * deleteFrames already manages this data one at a time, so the only time this\n * is necessary is if you poke around manually in `gd._transitionData._frames`\n * and create and haven't updated the lookup table.\n */plots.recomputeFrameHash=function(gd){var hash=gd._transitionData._frameHash={};var frames=gd._transitionData._frames;for(var i=0;i0){gd._transitioningWithDuration=true;}// If another transition is triggered, this callback will be executed simply because it's\n// in the interruptCallbacks queue. If this transition completes, it will instead flush\n// that queue and forget about this callback.\ngd._transitionData._interruptCallbacks.push(function(){aborted=true;});if(opts.redraw){gd._transitionData._interruptCallbacks.push(function(){return Registry.call('redraw',gd);});}// Emit this and make sure it happens last:\ngd._transitionData._interruptCallbacks.push(function(){gd.emit('plotly_transitioninterrupted',[]);});// Construct callbacks that are executed on transition end. This ensures the d3 transitions\n// are *complete* before anything else is done.\nvar numCallbacks=0;var numCompleted=0;function makeCallback(){numCallbacks++;return function(){numCompleted++;// When all are complete, perform a redraw:\nif(!aborted&&numCompleted===numCallbacks){completeTransition(resolve);}};}opts.runFn(makeCallback);// If nothing else creates a callback, then this will trigger the completion in the next tick:\nsetTimeout(makeCallback());});}function completeTransition(callback){// This a simple workaround for tests which purge the graph before animations\n// have completed. That's not a very common case, so this is the simplest\n// fix.\nif(!gd._transitionData)return;flushCallbacks(gd._transitionData._interruptCallbacks);return Promise.resolve().then(function(){if(opts.redraw){return Registry.call('redraw',gd);}}).then(function(){// Set transitioning false again once the redraw has occurred. This is used, for example,\n// to prevent the trailing redraw from autoranging:\ngd._transitioning=false;gd._transitioningWithDuration=false;gd.emit('plotly_transitioned',[]);}).then(callback);}function interruptPreviousTransitions(){// Fail-safe against purged plot:\nif(!gd._transitionData)return;// If a transition is interrupted, set this to false. At the moment, the only thing that would\n// interrupt a transition is another transition, so that it will momentarily be set to true\n// again, but this determines whether autorange or dragbox work, so it's for the sake of\n// cleanliness:\ngd._transitioning=false;return executeCallbacks(gd._transitionData._interruptCallbacks);}var seq=[plots.previousPromises,interruptPreviousTransitions,opts.prepareFn,plots.rehover,executeTransitions];var transitionStarting=Lib.syncOrAsync(seq,gd);if(!transitionStarting||!transitionStarting.then){transitionStarting=Promise.resolve();}return transitionStarting.then(function(){return gd;});}plots.doCalcdata=function(gd,traces){var axList=axisIDs.list(gd);var fullData=gd._fullData;var fullLayout=gd._fullLayout;var trace,_module,i,j;// XXX: Is this correct? Needs a closer look so that *some* traces can be recomputed without\n// *all* needing doCalcdata:\nvar calcdata=new Array(fullData.length);var oldCalcdata=(gd.calcdata||[]).slice();gd.calcdata=calcdata;// extra helper variables\n// how many box/violins plots do we have (in case they're grouped)\nfullLayout._numBoxes=0;fullLayout._numViolins=0;// initialize violin per-scale-group stats container\nfullLayout._violinScaleGroupStats={};// for calculating avg luminosity of heatmaps\ngd._hmpixcount=0;gd._hmlumcount=0;// for sharing colors across pies / sunbursts / treemap / funnelarea (and for legend)\nfullLayout._piecolormap={};fullLayout._sunburstcolormap={};fullLayout._treemapcolormap={};fullLayout._funnelareacolormap={};// If traces were specified and this trace was not included,\n// then transfer it over from the old calcdata:\nfor(i=0;i=0;j--){if(transforms[j].enabled){trace._indexToPoints=transforms[j]._indexToPoints;break;}}if(_module&&_module.calc){cd=_module.calc(gd,trace);}}// Make sure there is a first point.\n//\n// This ensures there is a calcdata item for every trace,\n// even if cartesian logic doesn't handle it (for things like legends).\nif(!Array.isArray(cd)||!cd[0]){cd=[{x:BADNUM,y:BADNUM}];}// add the trace-wide properties to the first point,\n// per point properties to every point\n// t is the holder for trace-wide properties\nif(!cd[0].t)cd[0].t={};cd[0].trace=trace;calcdata[i]=cd;}setupAxisCategories(axList,fullData,fullLayout);// 'transform' loop - must calc container traces first\n// so that if their dependent traces can get transform properly\nfor(i=0;i calcData hash\nfor(i=0;i calcData hash\nsubplot.traceHash=traceHash;};plots.plotBasePlot=function(desiredType,gd,traces,transitionOpts,makeOnCompleteCallback){var _module=Registry.getModule(desiredType);var cdmodule=getModuleCalcData(gd.calcdata,_module)[0];_module.plot(gd,cdmodule,transitionOpts,makeOnCompleteCallback);};plots.cleanBasePlot=function(desiredType,newFullData,newFullLayout,oldFullData,oldFullLayout){var had=oldFullLayout._has&&oldFullLayout._has(desiredType);var has=newFullLayout._has&&newFullLayout._has(desiredType);if(had&&!has){oldFullLayout['_'+desiredType+'layer'].selectAll('g.trace').remove();}};},{\"../components/color\":602,\"../constants/numerical\":711,\"../lib\":735,\"../plot_api/plot_schema\":772,\"../plot_api/plot_template\":773,\"../plots/get_data\":820,\"../registry\":866,\"./animation_attributes\":778,\"./attributes\":780,\"./cartesian/axis_ids\":786,\"./cartesian/handle_outline\":793,\"./command\":809,\"./font_attributes\":811,\"./frame_attributes\":812,\"./layout_attributes\":837,\"d3\":165,\"fast-isnumeric\":237}],847:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';module.exports={attr:'subplot',name:'polar',axisNames:['angularaxis','radialaxis'],axisName2dataArray:{angularaxis:'theta',radialaxis:'r'},layerNames:['draglayer','plotbg','backplot','angular-grid','radial-grid','frontplot','angular-line','radial-line','angular-axis','radial-axis'],radialDragBoxSize:50,angularDragBoxSize:30,cornerLen:25,cornerHalfWidth:2,// pixels to move mouse before you stop clamping to starting point\nMINDRAG:8,// smallest radial distance [px] allowed for a zoombox\nMINZOOM:20,// distance [px] off (r=0) or (r=radius) where we transition\n// from single-sided to two-sided radial zoom\nOFFEDGE:20};},{}],848:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Lib=_dereq_('../../lib');var polygonTester=_dereq_('../../lib/polygon').tester;var findIndexOfMin=Lib.findIndexOfMin;var isAngleInsideSector=Lib.isAngleInsideSector;var angleDelta=Lib.angleDelta;var angleDist=Lib.angleDist;/**\n * is pt (r,a) inside polygon made up vertices at angles 'vangles'\n * inside a given polar sector\n *\n * @param {number} r : pt's radial coordinate\n * @param {number} a : pt's angular coordinate in *radians*\n * @param {2-item array} rBnds : sector's radial bounds\n * @param {2-item array} aBnds : sector's angular bounds *radians*\n * @param {array} vangles : angles of polygon vertices in *radians*\n * @return {boolean}\n */function isPtInsidePolygon(r,a,rBnds,aBnds,vangles){if(!isAngleInsideSector(a,aBnds))return false;var r0,r1;if(rBnds[0] 'v1' edge with a ray at angle 'a'\n// (i.e. a line that starts from the origin at angle 'a')\n// given an (xp,yp) pair on the 'v0' <-> 'v1' line\n// (N.B. 'v0' and 'v1' are angles in radians)\nfunction findIntersectionXY(v0,v1,a,xpyp){var xstar,ystar;var xp=xpyp[0];var yp=xpyp[1];var dsin=clampTiny(Math.sin(v1)-Math.sin(v0));var dcos=clampTiny(Math.cos(v1)-Math.cos(v0));var tanA=Math.tan(a);var cotanA=clampTiny(1/tanA);var m=dsin/dcos;var b=yp-m*xp;if(cotanA){if(dsin&&dcos){// given\n// g(x) := v0 -> v1 line = m*x + b\n// h(x) := ray at angle 'a' = m*x = tanA*x\n// solve g(xstar) = h(xstar)\nxstar=b/(tanA-m);ystar=tanA*xstar;}else if(dcos){// horizontal v0 -> v1\nxstar=yp*cotanA;ystar=yp;}else{// vertical v0 -> v1\nxstar=xp;ystar=xp*tanA;}}else{// vertical ray\nif(dsin&&dcos){xstar=0;ystar=b;}else if(dcos){xstar=0;ystar=yp;}else{// does this case exists?\nxstar=ystar=NaN;}}return[xstar,ystar];}// solves l^2 = (f(x)^2 - yp)^2 + (x - xp)^2\n// rearranged into 0 = a*x^2 + b * x + c\n//\n// where f(x) = m*x + t + yp\n// and (x0, x1) = (-b +/- del) / (2*a)\nfunction findXYatLength(l,m,xp,yp){var t=-m*xp;var a=m*m+1;var b=2*(m*t-xp);var c=t*t+xp*xp-l*l;var del=Math.sqrt(b*b-4*a*c);var x0=(-b+del)/(2*a);var x1=(-b-del)/(2*a);return[[x0,m*x0+t+yp],[x1,m*x1+t+yp]];}function makeRegularPolygon(r,vangles){var len=vangles.length;var vertices=new Array(len+1);var i;for(i=0;i v[i0-1] edge with sector radius\nvar i0=findIndexOfMin(vangles,function(v){return isInside(v)?angleDist(v,a0):Infinity;});var xy0=findXY(vangles[i0],vangles[cycleIndex(i0-1)],a0);vertices.push(xy0);// fill in in-sector vertices\nfor(i=i0,j=0;j v[iN+1] edge with sector radius\nvar iN=findIndexOfMin(vangles,function(v){return isInside(v)?angleDist(v,a1):Infinity;});var xyN=findXY(vangles[iN],vangles[cycleIndex(iN+1)],a1);vertices.push(xyN);vertices.push([0,0]);vertices.push(vertices[0].slice());return vertices;}function makePolygon(r,a0,a1,vangles){return Lib.isFullCircle([a0,a1])?makeRegularPolygon(r,vangles):makeClippedPolygon(r,a0,a1,vangles);}function findPolygonOffset(r,a0,a1,vangles){var minX=Infinity;var minY=Infinity;var vertices=makePolygon(r,a0,a1,vangles);for(var i=0;i0?adelta:Infinity;};var i0=findIndexOfMin(vangles,minFn);var i1=Lib.mod(i0+1,vangles.length);return[vangles[i0],vangles[i1]];}// to more easily catch 'almost zero' numbers in if-else blocks\nfunction clampTiny(v){return Math.abs(v)>1e-10?v:0;}function transformForSVG(pts0,cx,cy){cx=cx||0;cy=cy||0;var len=pts0.length;var pts1=new Array(len);for(var i=0;i range[0], and vice-versa for `autorange: 'reversed'` below.\naxOut._m=1;switch(axName){case'radialaxis':var autoRange=coerceAxis('autorange',!axOut.isValidRange(axIn.range));axIn.autorange=autoRange;if(autoRange&&(axType==='linear'||axType==='-'))coerceAxis('rangemode');if(autoRange==='reversed')axOut._m=-1;coerceAxis('range');axOut.cleanRange('range',{dfltRange:[0,1]});if(visible){coerceAxis('side');coerceAxis('angle',sector[0]);coerceAxis('title.text');Lib.coerceFont(coerceAxis,'title.font',{family:opts.font.family,size:Math.round(opts.font.size*1.2),color:dfltFontColor});}break;case'angularaxis':// We do not support 'true' date angular axes yet,\n// users can still plot dates on angular axes by setting\n// `angularaxis.type: 'category'`.\n//\n// Here, if a date angular axes is detected, we make\n// all its corresponding traces invisible, so that\n// when we do add support for data angular axes, the new\n// behavior won't conflict with existing behavior\nif(axType==='date'){Lib.log('Polar plots do not support date angular axes yet.');for(var j=0;j=0;var angularDomain=useProvidedDomain?axisConfig.angularAxis.domain:d3.extent(angularDataMerged);var angularDomainStep=Math.abs(angularDataMerged[1]-angularDataMerged[0]);if(hasOnlyLineOrDotPlot&&!isOrdinal)angularDomainStep=0;var angularDomainWithPadding=angularDomain.slice();if(needsEndSpacing&&isOrdinal)angularDomainWithPadding[1]+=angularDomainStep;var tickCount=axisConfig.angularAxis.ticksCount||4;if(tickCount>8)tickCount=tickCount/(tickCount/8)+tickCount%8;if(axisConfig.angularAxis.ticksStep){tickCount=(angularDomainWithPadding[1]-angularDomainWithPadding[0])/tickCount;}var angularTicksStep=axisConfig.angularAxis.ticksStep||(angularDomainWithPadding[1]-angularDomainWithPadding[0])/(tickCount*(axisConfig.minorTicks+1));if(ticks)angularTicksStep=Math.max(Math.round(angularTicksStep),1);if(!angularDomainWithPadding[2])angularDomainWithPadding[2]=angularTicksStep;var angularAxisRange=d3.range.apply(this,angularDomainWithPadding);angularAxisRange=angularAxisRange.map(function(d,i){return parseFloat(d.toPrecision(12));});angularScale=d3.scale.linear().domain(angularDomainWithPadding.slice(0,2)).range(axisConfig.direction==='clockwise'?[0,360]:[360,0]);liveConfig.layout.angularAxis.domain=angularScale.domain();liveConfig.layout.angularAxis.endPadding=needsEndSpacing?angularDomainStep:0;svg=d3.select(this).select('svg.chart-root');if(typeof svg==='undefined'||svg.empty()){var skeleton=\"' + '' + '' + ' ' + ' ' + '' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' \";var doc=new DOMParser().parseFromString(skeleton,'application/xml');var newSvg=this.appendChild(this.ownerDocument.importNode(doc.documentElement,true));svg=d3.select(newSvg);}svg.select('.guides-group').style({'pointer-events':'none'});svg.select('.angular.axis-group').style({'pointer-events':'none'});svg.select('.radial.axis-group').style({'pointer-events':'none'});var chartGroup=svg.select('.chart-group');var lineStyle={fill:'none',stroke:axisConfig.tickColor};var fontStyle={'font-size':axisConfig.font.size,'font-family':axisConfig.font.family,fill:axisConfig.font.color,'text-shadow':['-1px 0px','1px -1px','-1px 1px','1px 1px'].map(function(d,i){return' '+d+' 0 '+axisConfig.font.outlineColor;}).join(',')};var legendContainer;if(axisConfig.showLegend){legendContainer=svg.select('.legend-group').attr({transform:'translate('+[radius,axisConfig.margin.top]+')'}).style({display:'block'});var elements=data.map(function(d,i){var datumClone=µ.util.cloneJson(d);datumClone.symbol=d.geometry==='DotPlot'?d.dotType||'circle':d.geometry!='LinePlot'?'square':'line';datumClone.visibleInLegend=typeof d.visibleInLegend==='undefined'||d.visibleInLegend;datumClone.color=d.geometry==='LinePlot'?d.strokeColor:d.color;return datumClone;});µ.Legend().config({data:data.map(function(d,i){return d.name||'Element'+i;}),legendConfig:extendDeepAll({},µ.Legend.defaultConfig().legendConfig,{container:legendContainer,elements:elements,reverseOrder:axisConfig.legend.reverseOrder})})();var legendBBox=legendContainer.node().getBBox();radius=Math.min(axisConfig.width-legendBBox.width-axisConfig.margin.left-axisConfig.margin.right,axisConfig.height-axisConfig.margin.top-axisConfig.margin.bottom)/2;radius=Math.max(10,radius);chartCenter=[axisConfig.margin.left+radius,axisConfig.margin.top+radius];radialScale.range([0,radius]);liveConfig.layout.radialAxis.domain=radialScale.domain();legendContainer.attr('transform','translate('+[chartCenter[0]+radius,chartCenter[1]-radius]+')');}else{legendContainer=svg.select('.legend-group').style({display:'none'});}svg.attr({width:axisConfig.width,height:axisConfig.height}).style({opacity:axisConfig.opacity});chartGroup.attr('transform','translate('+chartCenter+')').style({cursor:'crosshair'});var centeringOffset=[(axisConfig.width-(axisConfig.margin.left+axisConfig.margin.right+radius*2+(legendBBox?legendBBox.width:0)))/2,(axisConfig.height-(axisConfig.margin.top+axisConfig.margin.bottom+radius*2))/2];centeringOffset[0]=Math.max(0,centeringOffset[0]);centeringOffset[1]=Math.max(0,centeringOffset[1]);svg.select('.outer-group').attr('transform','translate('+centeringOffset+')');if(axisConfig.title&&axisConfig.title.text){var title=svg.select('g.title-group text').style(fontStyle).text(axisConfig.title.text);var titleBBox=title.node().getBBox();title.attr({x:chartCenter[0]-titleBBox.width/2,y:chartCenter[1]-radius-20});}var radialAxis=svg.select('.radial.axis-group');if(axisConfig.radialAxis.gridLinesVisible){var gridCircles=radialAxis.selectAll('circle.grid-circle').data(radialScale.ticks(5));gridCircles.enter().append('circle').attr({'class':'grid-circle'}).style(lineStyle);gridCircles.attr('r',radialScale);gridCircles.exit().remove();}radialAxis.select('circle.outside-circle').attr({r:radius}).style(lineStyle);var backgroundCircle=svg.select('circle.background-circle').attr({r:radius}).style({fill:axisConfig.backgroundColor,stroke:axisConfig.stroke});function currentAngle(d,i){return angularScale(d)%360+axisConfig.orientation;}if(axisConfig.radialAxis.visible){var axis=d3.svg.axis().scale(radialScale).ticks(5).tickSize(5);radialAxis.call(axis).attr({transform:'rotate('+axisConfig.radialAxis.orientation+')'});radialAxis.selectAll('.domain').style(lineStyle);radialAxis.selectAll('g>text').text(function(d,i){return this.textContent+axisConfig.radialAxis.ticksSuffix;}).style(fontStyle).style({'text-anchor':'start'}).attr({x:0,y:0,dx:0,dy:0,transform:function(d,i){if(axisConfig.radialAxis.tickOrientation==='horizontal'){return'rotate('+-axisConfig.radialAxis.orientation+') translate('+[0,fontStyle['font-size']]+')';}else return'translate('+[0,fontStyle['font-size']]+')';}});radialAxis.selectAll('g>line').style({stroke:'black'});}var angularAxis=svg.select('.angular.axis-group').selectAll('g.angular-tick').data(angularAxisRange);var angularAxisEnter=angularAxis.enter().append('g').classed('angular-tick',true);angularAxis.attr({transform:function(d,i){return'rotate('+currentAngle(d,i)+')';}}).style({display:axisConfig.angularAxis.visible?'block':'none'});angularAxis.exit().remove();angularAxisEnter.append('line').classed('grid-line',true).classed('major',function(d,i){return i%(axisConfig.minorTicks+1)==0;}).classed('minor',function(d,i){return!(i%(axisConfig.minorTicks+1)==0);}).style(lineStyle);angularAxisEnter.selectAll('.minor').style({stroke:axisConfig.minorTickColor});angularAxis.select('line.grid-line').attr({x1:axisConfig.tickLength?radius-axisConfig.tickLength:0,x2:radius}).style({display:axisConfig.angularAxis.gridLinesVisible?'block':'none'});angularAxisEnter.append('text').classed('axis-text',true).style(fontStyle);var ticksText=angularAxis.select('text.axis-text').attr({x:radius+axisConfig.labelOffset,dy:MID_SHIFT+'em',transform:function(d,i){var angle=currentAngle(d,i);var rad=radius+axisConfig.labelOffset;var orient=axisConfig.angularAxis.tickOrientation;if(orient=='horizontal')return'rotate('+-angle+' '+rad+' 0)';else if(orient=='radial')return angle<270&&angle>90?'rotate(180 '+rad+' 0)':null;else return'rotate('+(angle<=180&&angle>0?-90:90)+' '+rad+' 0)';}}).style({'text-anchor':'middle',display:axisConfig.angularAxis.labelsVisible?'block':'none'}).text(function(d,i){if(i%(axisConfig.minorTicks+1)!=0)return'';if(ticks){return ticks[d]+axisConfig.angularAxis.ticksSuffix;}else return d+axisConfig.angularAxis.ticksSuffix;}).style(fontStyle);if(axisConfig.angularAxis.rewriteTicks)ticksText.text(function(d,i){if(i%(axisConfig.minorTicks+1)!=0)return'';return axisConfig.angularAxis.rewriteTicks(this.textContent,i);});var rightmostTickEndX=d3.max(chartGroup.selectAll('.angular-tick text')[0].map(function(d,i){return d.getCTM().e+d.getBBox().width;}));legendContainer.attr({transform:'translate('+[radius+rightmostTickEndX,axisConfig.margin.top]+')'});var hasGeometry=svg.select('g.geometry-group').selectAll('g').size()>0;var geometryContainer=svg.select('g.geometry-group').selectAll('g.geometry').data(data);geometryContainer.enter().append('g').attr({'class':function(d,i){return'geometry geometry'+i;}});geometryContainer.exit().remove();if(data[0]||hasGeometry){var geometryConfigs=[];data.forEach(function(d,i){var geometryConfig={};geometryConfig.radialScale=radialScale;geometryConfig.angularScale=angularScale;geometryConfig.container=geometryContainer.filter(function(dB,iB){return iB==i;});geometryConfig.geometry=d.geometry;geometryConfig.orientation=axisConfig.orientation;geometryConfig.direction=axisConfig.direction;geometryConfig.index=i;geometryConfigs.push({data:d,geometryConfig:geometryConfig});});var geometryConfigsGrouped=d3.nest().key(function(d,i){return typeof d.data.groupId!='undefined'||'unstacked';}).entries(geometryConfigs);var geometryConfigsGrouped2=[];geometryConfigsGrouped.forEach(function(d,i){if(d.key==='unstacked')geometryConfigsGrouped2=geometryConfigsGrouped2.concat(d.values.map(function(d,i){return[d];}));else geometryConfigsGrouped2.push(d.values);});geometryConfigsGrouped2.forEach(function(d,i){var geometry;if(Array.isArray(d))geometry=d[0].geometryConfig.geometry;else geometry=d.geometryConfig.geometry;var finalGeometryConfig=d.map(function(dB,iB){return extendDeepAll(µ[geometry].defaultConfig(),dB);});µ[geometry]().config(finalGeometryConfig)();});}var guides=svg.select('.guides-group');var tooltipContainer=svg.select('.tooltips-group');var angularTooltip=µ.tooltipPanel().config({container:tooltipContainer,fontSize:8})();var radialTooltip=µ.tooltipPanel().config({container:tooltipContainer,fontSize:8})();var geometryTooltip=µ.tooltipPanel().config({container:tooltipContainer,hasTick:true})();var angularValue,radialValue;if(!isOrdinal){var angularGuideLine=guides.select('line').attr({x1:0,y1:0,y2:0}).style({stroke:'grey','pointer-events':'none'});chartGroup.on('mousemove.angular-guide',function(d,i){var mouseAngle=µ.util.getMousePos(backgroundCircle).angle;angularGuideLine.attr({x2:-radius,transform:'rotate('+mouseAngle+')'}).style({opacity:.5});var angleWithOriginOffset=(mouseAngle+180+360-axisConfig.orientation)%360;angularValue=angularScale.invert(angleWithOriginOffset);var pos=µ.util.convertToCartesian(radius+12,mouseAngle+180);angularTooltip.text(µ.util.round(angularValue)).move([pos[0]+chartCenter[0],pos[1]+chartCenter[1]]);}).on('mouseout.angular-guide',function(d,i){guides.select('line').style({opacity:0});});}var angularGuideCircle=guides.select('circle').style({stroke:'grey',fill:'none'});chartGroup.on('mousemove.radial-guide',function(d,i){var r=µ.util.getMousePos(backgroundCircle).radius;angularGuideCircle.attr({r:r}).style({opacity:.5});radialValue=radialScale.invert(µ.util.getMousePos(backgroundCircle).radius);var pos=µ.util.convertToCartesian(r,axisConfig.radialAxis.orientation);radialTooltip.text(µ.util.round(radialValue)).move([pos[0]+chartCenter[0],pos[1]+chartCenter[1]]);}).on('mouseout.radial-guide',function(d,i){angularGuideCircle.style({opacity:0});geometryTooltip.hide();angularTooltip.hide();radialTooltip.hide();});svg.selectAll('.geometry-group .mark').on('mouseover.tooltip',function(d,i){var el=d3.select(this);var color=this.style.fill;var newColor='black';var opacity=this.style.opacity||1;el.attr({'data-opacity':opacity});if(color&&color!=='none'){el.attr({'data-fill':color});newColor=d3.hsl(color).darker().toString();el.style({fill:newColor,opacity:1});var textData={t:µ.util.round(d[0]),r:µ.util.round(d[1])};if(isOrdinal)textData.t=ticks[d[0]];var text='t: '+textData.t+', r: '+textData.r;var bbox=this.getBoundingClientRect();var svgBBox=svg.node().getBoundingClientRect();var pos=[bbox.left+bbox.width/2-centeringOffset[0]-svgBBox.left,bbox.top+bbox.height/2-centeringOffset[1]-svgBBox.top];geometryTooltip.config({color:newColor}).text(text);geometryTooltip.move(pos);}else{color=this.style.stroke||'black';el.attr({'data-stroke':color});newColor=d3.hsl(color).darker().toString();el.style({stroke:newColor,opacity:1});}}).on('mousemove.tooltip',function(d,i){if(d3.event.which!=0)return false;if(d3.select(this).attr('data-fill'))geometryTooltip.show();}).on('mouseout.tooltip',function(d,i){geometryTooltip.hide();var el=d3.select(this);var fillColor=el.attr('data-fill');if(fillColor)el.style({fill:fillColor,opacity:el.attr('data-opacity')});else el.style({stroke:el.attr('data-stroke'),opacity:el.attr('data-opacity')});});});return exports;}exports.render=function(_container){render(_container);return this;};exports.config=function(_x){if(!arguments.length)return config;var xClone=µ.util.cloneJson(_x);xClone.data.forEach(function(d,i){if(!config.data[i])config.data[i]={};extendDeepAll(config.data[i],µ.Axis.defaultConfig().data[0]);extendDeepAll(config.data[i],d);});extendDeepAll(config.layout,µ.Axis.defaultConfig().layout);extendDeepAll(config.layout,xClone.layout);return this;};exports.getLiveConfig=function(){return liveConfig;};exports.getinputConfig=function(){return inputConfig;};exports.radialScale=function(_x){return radialScale;};exports.angularScale=function(_x){return angularScale;};exports.svg=function(){return svg;};d3.rebind(exports,dispatch,'on');return exports;};µ.Axis.defaultConfig=function(d,i){var config={data:[{t:[1,2,3,4],r:[10,11,12,13],name:'Line1',geometry:'LinePlot',color:null,strokeDash:'solid',strokeColor:null,strokeSize:'1',visibleInLegend:true,opacity:1}],layout:{defaultColorRange:d3.scale.category10().range(),title:null,height:450,width:500,margin:{top:40,right:40,bottom:40,left:40},font:{size:12,color:'gray',outlineColor:'white',family:'Tahoma, sans-serif'},direction:'clockwise',orientation:0,labelOffset:10,radialAxis:{domain:null,orientation:-45,ticksSuffix:'',visible:true,gridLinesVisible:true,tickOrientation:'horizontal',rewriteTicks:null},angularAxis:{domain:[0,360],ticksSuffix:'',visible:true,gridLinesVisible:true,labelsVisible:true,tickOrientation:'horizontal',rewriteTicks:null,ticksCount:null,ticksStep:null},minorTicks:0,tickLength:null,tickColor:'silver',minorTickColor:'#eee',backgroundColor:'none',needsEndSpacing:null,showLegend:true,legend:{reverseOrder:false},opacity:1}};return config;};µ.util={};µ.DATAEXTENT='dataExtent';µ.AREA='AreaChart';µ.LINE='LinePlot';µ.DOT='DotPlot';µ.BAR='BarChart';µ.util._override=function(_objA,_objB){for(var x in _objA)if(x in _objB)_objB[x]=_objA[x];};µ.util._extend=function(_objA,_objB){for(var x in _objA)_objB[x]=_objA[x];};µ.util._rndSnd=function(){return Math.random()*2-1+(Math.random()*2-1)+(Math.random()*2-1);};µ.util.dataFromEquation2=function(_equation,_step){var step=_step||6;var data=d3.range(0,360+step,step).map(function(deg,index){var theta=deg*Math.PI/180;var radius=_equation(theta);return[deg,radius];});return data;};µ.util.dataFromEquation=function(_equation,_step,_name){var step=_step||6;var t=[],r=[];d3.range(0,360+step,step).forEach(function(deg,index){var theta=deg*Math.PI/180;var radius=_equation(theta);t.push(deg);r.push(radius);});var result={t:t,r:r};if(_name)result.name=_name;return result;};µ.util.ensureArray=function(_val,_count){if(typeof _val==='undefined')return null;var arr=[].concat(_val);return d3.range(_count).map(function(d,i){return arr[i]||arr[0];});};µ.util.fillArrays=function(_obj,_valueNames,_count){_valueNames.forEach(function(d,i){_obj[d]=µ.util.ensureArray(_obj[d],_count);});return _obj;};µ.util.cloneJson=function(json){return JSON.parse(JSON.stringify(json));};µ.util.validateKeys=function(obj,keys){if(typeof keys==='string')keys=keys.split('.');var next=keys.shift();return obj[next]&&(!keys.length||objHasKeys(obj[next],keys));};µ.util.sumArrays=function(a,b){return d3.zip(a,b).map(function(d,i){return d3.sum(d);});};µ.util.arrayLast=function(a){return a[a.length-1];};µ.util.arrayEqual=function(a,b){var i=Math.max(a.length,b.length,1);while(i-->=0&&a[i]===b[i]);return i===-2;};µ.util.flattenArray=function(arr){var r=[];while(!µ.util.arrayEqual(r,arr)){r=arr;arr=[].concat.apply([],arr);}return arr;};µ.util.deduplicate=function(arr){return arr.filter(function(v,i,a){return a.indexOf(v)==i;});};µ.util.convertToCartesian=function(radius,theta){var thetaRadians=theta*Math.PI/180;var x=radius*Math.cos(thetaRadians);var y=radius*Math.sin(thetaRadians);return[x,y];};µ.util.round=function(_value,_digits){var digits=_digits||2;var mult=Math.pow(10,digits);return Math.round(_value*mult)/mult;};µ.util.getMousePos=function(_referenceElement){var mousePos=d3.mouse(_referenceElement.node());var mouseX=mousePos[0];var mouseY=mousePos[1];var mouse={};mouse.x=mouseX;mouse.y=mouseY;mouse.pos=mousePos;mouse.angle=(Math.atan2(mouseY,mouseX)+Math.PI)*180/Math.PI;mouse.radius=Math.sqrt(mouseX*mouseX+mouseY*mouseY);return mouse;};µ.util.duplicatesCount=function(arr){var uniques={},val;var dups={};for(var i=0,len=arr.length;i0)return;var lineSelection=d3.select(this.parentNode).selectAll('path.line').data([0]);lineSelection.enter().insert('path');lineSelection.attr({'class':'line',d:line(lineData),transform:function(dB,iB){return'rotate('+(geometryConfig.orientation+90)+')';},'pointer-events':'none'}).style({fill:function(dB,iB){return markStyle.fill(d,i,pI);},'fill-opacity':0,stroke:function(dB,iB){return markStyle.stroke(d,i,pI);},'stroke-width':function(dB,iB){return markStyle['stroke-width'](d,i,pI);},'stroke-dasharray':function(dB,iB){return markStyle['stroke-dasharray'](d,i,pI);},opacity:function(dB,iB){return markStyle.opacity(d,i,pI);},display:function(dB,iB){return markStyle.display(d,i,pI);}});};var angularRange=geometryConfig.angularScale.range();var triangleAngle=Math.abs(angularRange[1]-angularRange[0])/data[0].length*Math.PI/180;var arc=d3.svg.arc().startAngle(function(d){return-triangleAngle/2;}).endAngle(function(d){return triangleAngle/2;}).innerRadius(function(d){return geometryConfig.radialScale(domainMin+(d[2]||0));}).outerRadius(function(d){return geometryConfig.radialScale(domainMin+(d[2]||0))+geometryConfig.radialScale(d[1]);});generator.arc=function(d,i,pI){d3.select(this).attr({'class':'mark arc',d:arc,transform:function(d,i){return'rotate('+(geometryConfig.orientation+angularScale(d[0])+90)+')';}});};var markStyle={fill:function(d,i,pI){return _config[pI].data.color;},stroke:function(d,i,pI){return _config[pI].data.strokeColor;},'stroke-width':function(d,i,pI){return _config[pI].data.strokeSize+'px';},'stroke-dasharray':function(d,i,pI){return dashArray[_config[pI].data.strokeDash];},opacity:function(d,i,pI){return _config[pI].data.opacity;},display:function(d,i,pI){return typeof _config[pI].data.visible==='undefined'||_config[pI].data.visible?'block':'none';}};var geometryLayer=d3.select(this).selectAll('g.layer').data(data);geometryLayer.enter().append('g').attr({'class':'layer'});var geometry=geometryLayer.selectAll('path.mark').data(function(d,i){return d;});geometry.enter().append('path').attr({'class':'mark'});geometry.style(markStyle).each(generator[geometryConfig.geometryType]);geometry.exit().remove();geometryLayer.exit().remove();function getPolarCoordinates(d,i){var r=geometryConfig.radialScale(d[1]);var t=(geometryConfig.angularScale(d[0])+geometryConfig.orientation)*Math.PI/180;return{r:r,t:t};}function convertToCartesian(polarCoordinates){var x=polarCoordinates.r*Math.cos(polarCoordinates.t);var y=polarCoordinates.r*Math.sin(polarCoordinates.t);return{x:x,y:y};}});}exports.config=function(_x){if(!arguments.length)return config;_x.forEach(function(d,i){if(!config[i])config[i]={};extendDeepAll(config[i],µ.PolyChart.defaultConfig());extendDeepAll(config[i],d);});return this;};exports.getColorScale=function(){return colorScale;};d3.rebind(exports,dispatch,'on');return exports;};µ.PolyChart.defaultConfig=function(){var config={data:{name:'geom1',t:[[1,2,3,4]],r:[[1,2,3,4]],dotType:'circle',dotSize:64,dotVisible:false,barWidth:20,color:'#ffa500',strokeSize:1,strokeColor:'silver',strokeDash:'solid',opacity:1,index:0,visible:true,visibleInLegend:true},geometryConfig:{geometry:'LinePlot',geometryType:'arc',direction:'clockwise',orientation:0,container:'body',radialScale:null,angularScale:null,colorScale:d3.scale.category20()}};return config;};µ.BarChart=function module(){return µ.PolyChart();};µ.BarChart.defaultConfig=function(){var config={geometryConfig:{geometryType:'bar'}};return config;};µ.AreaChart=function module(){return µ.PolyChart();};µ.AreaChart.defaultConfig=function(){var config={geometryConfig:{geometryType:'arc'}};return config;};µ.DotPlot=function module(){return µ.PolyChart();};µ.DotPlot.defaultConfig=function(){var config={geometryConfig:{geometryType:'dot',dotType:'circle'}};return config;};µ.LinePlot=function module(){return µ.PolyChart();};µ.LinePlot.defaultConfig=function(){var config={geometryConfig:{geometryType:'line'}};return config;};µ.Legend=function module(){var config=µ.Legend.defaultConfig();var dispatch=d3.dispatch('hover');function exports(){var legendConfig=config.legendConfig;var flattenData=config.data.map(function(d,i){return[].concat(d).map(function(dB,iB){var element=extendDeepAll({},legendConfig.elements[i]);element.name=dB;element.color=[].concat(legendConfig.elements[i].color)[iB];return element;});});var data=d3.merge(flattenData);data=data.filter(function(d,i){return legendConfig.elements[i]&&(legendConfig.elements[i].visibleInLegend||typeof legendConfig.elements[i].visibleInLegend==='undefined');});if(legendConfig.reverseOrder)data=data.reverse();var container=legendConfig.container;if(typeof container=='string'||container.nodeName)container=d3.select(container);var colors=data.map(function(d,i){return d.color;});var lineHeight=legendConfig.fontSize;var isContinuous=legendConfig.isContinuous==null?typeof data[0]==='number':legendConfig.isContinuous;var height=isContinuous?legendConfig.height:lineHeight*data.length;var legendContainerGroup=container.classed('legend-group',true);var svg=legendContainerGroup.selectAll('svg').data([0]);var svgEnter=svg.enter().append('svg').attr({width:300,height:height+lineHeight,xmlns:'http://www.w3.org/2000/svg','xmlns:xlink':'http://www.w3.org/1999/xlink',version:'1.1'});svgEnter.append('g').classed('legend-axis',true);svgEnter.append('g').classed('legend-marks',true);var dataNumbered=d3.range(data.length);var colorScale=d3.scale[isContinuous?'linear':'ordinal']().domain(dataNumbered).range(colors);var dataScale=d3.scale[isContinuous?'linear':'ordinal']().domain(dataNumbered)[isContinuous?'range':'rangePoints']([0,height]);var shapeGenerator=function(_type,_size){var squareSize=_size*3;if(_type==='line'){return'M'+[[-_size/2,-_size/12],[_size/2,-_size/12],[_size/2,_size/12],[-_size/2,_size/12]]+'Z';}else if(d3.svg.symbolTypes.indexOf(_type)!=-1)return d3.svg.symbol().type(_type).size(squareSize)();else return d3.svg.symbol().type('square').size(squareSize)();};if(isContinuous){var gradient=svg.select('.legend-marks').append('defs').append('linearGradient').attr({id:'grad1',x1:'0%',y1:'0%',x2:'0%',y2:'100%'}).selectAll('stop').data(colors);gradient.enter().append('stop');gradient.attr({offset:function(d,i){return i/(colors.length-1)*100+'%';}}).style({'stop-color':function(d,i){return d;}});svg.append('rect').classed('legend-mark',true).attr({height:legendConfig.height,width:legendConfig.colorBandWidth,fill:'url(#grad1)'});}else{var legendElement=svg.select('.legend-marks').selectAll('path.legend-mark').data(data);legendElement.enter().append('path').classed('legend-mark',true);legendElement.attr({transform:function(d,i){return'translate('+[lineHeight/2,dataScale(i)+lineHeight/2]+')';},d:function(d,i){var symbolType=d.symbol;return shapeGenerator(symbolType,lineHeight);},fill:function(d,i){return colorScale(i);}});legendElement.exit().remove();}var legendAxis=d3.svg.axis().scale(dataScale).orient('right');var axis=svg.select('g.legend-axis').attr({transform:'translate('+[isContinuous?legendConfig.colorBandWidth:lineHeight,lineHeight/2]+')'}).call(legendAxis);axis.selectAll('.domain').style({fill:'none',stroke:'none'});axis.selectAll('line').style({fill:'none',stroke:isContinuous?legendConfig.textColor:'none'});axis.selectAll('text').style({fill:legendConfig.textColor,'font-size':legendConfig.fontSize}).text(function(d,i){return data[i].name;});return exports;}exports.config=function(_x){if(!arguments.length)return config;extendDeepAll(config,_x);return this;};d3.rebind(exports,dispatch,'on');return exports;};µ.Legend.defaultConfig=function(d,i){var config={data:['a','b','c'],legendConfig:{elements:[{symbol:'line',color:'red'},{symbol:'square',color:'yellow'},{symbol:'diamond',color:'limegreen'}],height:150,colorBandWidth:30,fontSize:12,container:'body',isContinuous:null,textColor:'grey',reverseOrder:false}};return config;};µ.tooltipPanel=function(){var tooltipEl,tooltipTextEl,backgroundEl;var config={container:null,hasTick:false,fontSize:12,color:'white',padding:5};var id='tooltip-'+µ.tooltipPanel.uid++;var tickSize=10;var exports=function(){tooltipEl=config.container.selectAll('g.'+id).data([0]);var tooltipEnter=tooltipEl.enter().append('g').classed(id,true).style({'pointer-events':'none',display:'none'});backgroundEl=tooltipEnter.append('path').style({fill:'white','fill-opacity':.9}).attr({d:'M0 0'});tooltipTextEl=tooltipEnter.append('text').attr({dx:config.padding+tickSize,dy:+config.fontSize*.3});return exports;};exports.text=function(_text){var l=d3.hsl(config.color).l;var strokeColor=l>=.5?'#aaa':'white';var fillColor=l>=.5?'black':'white';var text=_text||'';tooltipTextEl.style({fill:fillColor,'font-size':config.fontSize+'px'}).text(text);var padding=config.padding;var bbox=tooltipTextEl.node().getBBox();var boxStyle={fill:config.color,stroke:strokeColor,'stroke-width':'2px'};var backGroundW=bbox.width+padding*2+tickSize;var backGroundH=bbox.height+padding*2;backgroundEl.attr({d:'M'+[[tickSize,-backGroundH/2],[tickSize,-backGroundH/4],[config.hasTick?0:tickSize,0],[tickSize,backGroundH/4],[tickSize,backGroundH/2],[backGroundW,backGroundH/2],[backGroundW,-backGroundH/2]].join('L')+'Z'}).style(boxStyle);tooltipEl.attr({transform:'translate('+[tickSize,-backGroundH/2+padding*2]+')'});tooltipEl.style({display:'block'});return exports;};exports.move=function(_pos){if(!tooltipEl)return;tooltipEl.attr({transform:'translate('+[_pos[0],_pos[1]]+')'}).style({display:'block'});return exports;};exports.hide=function(){if(!tooltipEl)return;tooltipEl.style({display:'none'});return exports;};exports.show=function(){if(!tooltipEl)return;tooltipEl.style({display:'block'});return exports;};exports.config=function(_x){extendDeepAll(config,_x);return exports;};return exports;};µ.tooltipPanel.uid=1;µ.adapter={};µ.adapter.plotly=function module(){var exports={};exports.convert=function(_inputConfig,reverse){var outputConfig={};if(_inputConfig.data){outputConfig.data=_inputConfig.data.map(function(d,i){var r=extendDeepAll({},d);var toTranslate=[[r,['marker','color'],['color']],[r,['marker','opacity'],['opacity']],[r,['marker','line','color'],['strokeColor']],[r,['marker','line','dash'],['strokeDash']],[r,['marker','line','width'],['strokeSize']],[r,['marker','symbol'],['dotType']],[r,['marker','size'],['dotSize']],[r,['marker','barWidth'],['barWidth']],[r,['line','interpolation'],['lineInterpolation']],[r,['showlegend'],['visibleInLegend']]];toTranslate.forEach(function(d,i){µ.util.translator.apply(null,d.concat(reverse));});if(!reverse)delete r.marker;if(reverse)delete r.groupId;if(!reverse){if(r.type==='scatter'){if(r.mode==='lines')r.geometry='LinePlot';else if(r.mode==='markers')r.geometry='DotPlot';else if(r.mode==='lines+markers'){r.geometry='LinePlot';r.dotVisible=true;}}else if(r.type==='area')r.geometry='AreaChart';else if(r.type==='bar')r.geometry='BarChart';delete r.mode;delete r.type;}else{if(r.geometry==='LinePlot'){r.type='scatter';if(r.dotVisible===true){delete r.dotVisible;r.mode='lines+markers';}else r.mode='lines';}else if(r.geometry==='DotPlot'){r.type='scatter';r.mode='markers';}else if(r.geometry==='AreaChart')r.type='area';else if(r.geometry==='BarChart')r.type='bar';delete r.geometry;}return r;});if(!reverse&&_inputConfig.layout&&_inputConfig.layout.barmode==='stack'){var duplicates=µ.util.duplicates(outputConfig.data.map(function(d,i){return d.geometry;}));outputConfig.data.forEach(function(d,i){var idx=duplicates.indexOf(d.geometry);if(idx!=-1)outputConfig.data[i].groupId=idx;});}}if(_inputConfig.layout){var r=extendDeepAll({},_inputConfig.layout);var toTranslate=[[r,['plot_bgcolor'],['backgroundColor']],[r,['showlegend'],['showLegend']],[r,['radialaxis'],['radialAxis']],[r,['angularaxis'],['angularAxis']],[r.angularaxis,['showline'],['gridLinesVisible']],[r.angularaxis,['showticklabels'],['labelsVisible']],[r.angularaxis,['nticks'],['ticksCount']],[r.angularaxis,['tickorientation'],['tickOrientation']],[r.angularaxis,['ticksuffix'],['ticksSuffix']],[r.angularaxis,['range'],['domain']],[r.angularaxis,['endpadding'],['endPadding']],[r.radialaxis,['showline'],['gridLinesVisible']],[r.radialaxis,['tickorientation'],['tickOrientation']],[r.radialaxis,['ticksuffix'],['ticksSuffix']],[r.radialaxis,['range'],['domain']],[r.angularAxis,['showline'],['gridLinesVisible']],[r.angularAxis,['showticklabels'],['labelsVisible']],[r.angularAxis,['nticks'],['ticksCount']],[r.angularAxis,['tickorientation'],['tickOrientation']],[r.angularAxis,['ticksuffix'],['ticksSuffix']],[r.angularAxis,['range'],['domain']],[r.angularAxis,['endpadding'],['endPadding']],[r.radialAxis,['showline'],['gridLinesVisible']],[r.radialAxis,['tickorientation'],['tickOrientation']],[r.radialAxis,['ticksuffix'],['ticksSuffix']],[r.radialAxis,['range'],['domain']],[r.font,['outlinecolor'],['outlineColor']],[r.legend,['traceorder'],['reverseOrder']],[r,['labeloffset'],['labelOffset']],[r,['defaultcolorrange'],['defaultColorRange']]];toTranslate.forEach(function(d,i){µ.util.translator.apply(null,d.concat(reverse));});if(!reverse){if(r.angularAxis&&typeof r.angularAxis.ticklen!=='undefined')r.tickLength=r.angularAxis.ticklen;if(r.angularAxis&&typeof r.angularAxis.tickcolor!=='undefined')r.tickColor=r.angularAxis.tickcolor;}else{if(typeof r.tickLength!=='undefined'){r.angularaxis.ticklen=r.tickLength;delete r.tickLength;}if(r.tickColor){r.angularaxis.tickcolor=r.tickColor;delete r.tickColor;}}if(r.legend&&typeof r.legend.reverseOrder!='boolean'){r.legend.reverseOrder=r.legend.reverseOrder!='normal';}if(r.legend&&typeof r.legend.traceorder=='boolean'){r.legend.traceorder=r.legend.traceorder?'reversed':'normal';delete r.legend.reverseOrder;}if(r.margin&&typeof r.margin.t!='undefined'){var source=['t','r','b','l','pad'];var target=['top','right','bottom','left','pad'];var margin={};d3.entries(r.margin).forEach(function(dB,iB){margin[target[source.indexOf(dB.key)]]=dB.value;});r.margin=margin;}if(reverse){delete r.needsEndSpacing;delete r.minorTickColor;delete r.minorTicks;delete r.angularaxis.ticksCount;delete r.angularaxis.ticksCount;delete r.angularaxis.ticksStep;delete r.angularaxis.rewriteTicks;delete r.angularaxis.nticks;delete r.radialaxis.ticksCount;delete r.radialaxis.ticksCount;delete r.radialaxis.ticksStep;delete r.radialaxis.rewriteTicks;delete r.radialaxis.nticks;}outputConfig.layout=r;}return outputConfig;};return exports;};},{\"../../../constants/alignment\":704,\"../../../lib\":735,\"d3\":165}],856:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/ /* eslint-disable new-cap */'use strict';var d3=_dereq_('d3');var Lib=_dereq_('../../../lib');var Color=_dereq_('../../../components/color');var micropolar=_dereq_('./micropolar');var UndoManager=_dereq_('./undo_manager');var extendDeepAll=Lib.extendDeepAll;var manager=module.exports={};manager.framework=function(_gd){var config,previousConfigClone,plot,convertedInput,container;var undoManager=new UndoManager();function exports(_inputConfig,_container){if(_container)container=_container;d3.select(d3.select(container).node().parentNode).selectAll('.svg-container>*:not(.chart-root)').remove();config=!config?_inputConfig:extendDeepAll(config,_inputConfig);if(!plot)plot=micropolar.Axis();convertedInput=micropolar.adapter.plotly().convert(config);plot.config(convertedInput).render(container);_gd.data=config.data;_gd.layout=config.layout;manager.fillLayout(_gd);return config;}exports.isPolar=true;exports.svg=function(){return plot.svg();};exports.getConfig=function(){return config;};exports.getLiveConfig=function(){return micropolar.adapter.plotly().convert(plot.getLiveConfig(),true);};exports.getLiveScales=function(){return{t:plot.angularScale(),r:plot.radialScale()};};exports.setUndoPoint=function(){var that=this;var configClone=micropolar.util.cloneJson(config);(function(_configClone,_previousConfigClone){undoManager.add({undo:function(){if(_previousConfigClone)that(_previousConfigClone);},redo:function(){that(_configClone);}});})(configClone,previousConfigClone);previousConfigClone=micropolar.util.cloneJson(configClone);};exports.undo=function(){undoManager.undo();};exports.redo=function(){undoManager.redo();};return exports;};manager.fillLayout=function(_gd){var container=d3.select(_gd).selectAll('.plot-container');var paperDiv=container.selectAll('.svg-container');var paper=_gd.framework&&_gd.framework.svg&&_gd.framework.svg();var dflts={width:800,height:600,paper_bgcolor:Color.background,_container:container,_paperdiv:paperDiv,_paper:paper};_gd._fullLayout=extendDeepAll(dflts,_gd.layout);};},{\"../../../components/color\":602,\"../../../lib\":735,\"./micropolar\":855,\"./undo_manager\":857,\"d3\":165}],857:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';// Modified from https://github.com/ArthurClemens/Javascript-Undo-Manager\n// Copyright (c) 2010-2013 Arthur Clemens, arthur@visiblearea.com\nmodule.exports=function UndoManager(){var undoCommands=[];var index=-1;var isExecuting=false;var callback;function execute(command,action){if(!command)return this;isExecuting=true;command[action]();isExecuting=false;return this;}return{add:function(command){if(isExecuting)return this;undoCommands.splice(index+1,undoCommands.length-index);undoCommands.push(command);index=undoCommands.length-1;return this;},setCallback:function(callbackFunc){callback=callbackFunc;},undo:function(){var command=undoCommands[index];if(!command)return this;execute(command,'undo');index-=1;if(callback)callback(command.undo);return this;},redo:function(){var command=undoCommands[index+1];if(!command)return this;execute(command,'redo');index+=1;if(callback)callback(command.redo);return this;},clear:function(){undoCommands=[];index=-1;},hasUndo:function(){return index!==-1;},hasRedo:function(){return index calcdata conversions (aka d2c) during the calc step\n *\n * - this.radialAxis\n * extends polarLayout.radialaxis, adds mocked 'domain' and\n * few other keys in order to reuse Cartesian doAutoRange and the Axes\n * drawing routines.\n * used for calcdata -> geometric conversions (aka c2g) during the plot step\n * + setGeometry setups ax.c2g for given ax.range\n * + setScale setups ax._m,ax._b for given ax.range\n *\n * - this.angularAxis\n * extends polarLayout.angularaxis, adds mocked 'range' and 'domain' and\n * a few other keys in order to reuse the Axes drawing routines.\n * used for calcdata -> geometric conversions (aka c2g) during the plot step\n * + setGeometry setups ax.c2g given ax.rotation, ax.direction & ax._categories,\n * and mocks ax.range\n * + setScale setups ax._m,ax._b with that mocked ax.range\n *\n * - this.xaxis\n * - this.yaxis\n * setup so that polar traces can reuse plot methods of Cartesian traces\n * which mostly rely on 2pixel methods (e.g ax.c2p)\n */proto.updateLayout=function(fullLayout,polarLayout){var _this=this;var layers=_this.layers;var gs=fullLayout._size;// axis attributes\nvar radialLayout=polarLayout.radialaxis;var angularLayout=polarLayout.angularaxis;// layout domains\nvar xDomain=polarLayout.domain.x;var yDomain=polarLayout.domain.y;// offsets from paper edge to layout domain box\n_this.xOffset=gs.l+gs.w*xDomain[0];_this.yOffset=gs.t+gs.h*(1-yDomain[1]);// lengths of the layout domain box\nvar xLength=_this.xLength=gs.w*(xDomain[1]-xDomain[0]);var yLength=_this.yLength=gs.h*(yDomain[1]-yDomain[0]);// sector to plot\nvar sector=polarLayout.sector;_this.sectorInRad=sector.map(deg2rad);var sectorBBox=_this.sectorBBox=computeSectorBBox(sector);var dxSectorBBox=sectorBBox[2]-sectorBBox[0];var dySectorBBox=sectorBBox[3]-sectorBBox[1];// aspect ratios\nvar arDomain=yLength/xLength;var arSector=Math.abs(dySectorBBox/dxSectorBBox);// actual lengths and domains of subplot box\nvar xLength2,yLength2;var xDomain2,yDomain2;var gap;if(arDomain>arSector){xLength2=xLength;yLength2=xLength*arSector;gap=(yLength-yLength2)/gs.h/2;xDomain2=[xDomain[0],xDomain[1]];yDomain2=[yDomain[0]+gap,yDomain[1]-gap];}else{xLength2=yLength/arSector;yLength2=yLength;gap=(xLength-xLength2)/gs.w/2;xDomain2=[xDomain[0]+gap,xDomain[1]-gap];yDomain2=[yDomain[0],yDomain[1]];}_this.xLength2=xLength2;_this.yLength2=yLength2;_this.xDomain2=xDomain2;_this.yDomain2=yDomain2;// actual offsets from paper edge to the subplot box top-left corner\nvar xOffset2=_this.xOffset2=gs.l+gs.w*xDomain2[0];var yOffset2=_this.yOffset2=gs.t+gs.h*(1-yDomain2[1]);// circle radius in px\nvar radius=_this.radius=xLength2/dxSectorBBox;// 'inner' radius in px (when polar.hole is set)\nvar innerRadius=_this.innerRadius=polarLayout.hole*radius;// circle center position in px\nvar cx=_this.cx=xOffset2-radius*sectorBBox[0];var cy=_this.cy=yOffset2+radius*sectorBBox[3];// circle center in the coordinate system of plot area\nvar cxx=_this.cxx=cx-xOffset2;var cyy=_this.cyy=cy-yOffset2;_this.radialAxis=_this.mockAxis(fullLayout,polarLayout,radialLayout,{// make this an 'x' axis to make positioning (especially rotation) easier\n_id:'x',// convert to 'x' axis equivalent\nside:{counterclockwise:'top',clockwise:'bottom'}[radialLayout.side],// spans length 1 radius\ndomain:[innerRadius/gs.w,radius/gs.w]});_this.angularAxis=_this.mockAxis(fullLayout,polarLayout,angularLayout,{side:'right',// to get auto nticks right\ndomain:[0,Math.PI],// don't pass through autorange logic\nautorange:false});_this.doAutoRange(fullLayout,polarLayout);// N.B. this sets _this.vangles\n_this.updateAngularAxis(fullLayout,polarLayout);// N.B. this sets _this.radialAxisAngle\n_this.updateRadialAxis(fullLayout,polarLayout);_this.updateRadialAxisTitle(fullLayout,polarLayout);_this.xaxis=_this.mockCartesianAxis(fullLayout,polarLayout,{_id:'x',domain:xDomain2});_this.yaxis=_this.mockCartesianAxis(fullLayout,polarLayout,{_id:'y',domain:yDomain2});var dPath=_this.pathSubplot();_this.clipPaths.forTraces.select('path').attr('d',dPath).attr('transform',strTranslate(cxx,cyy));layers.frontplot.attr('transform',strTranslate(xOffset2,yOffset2)).call(Drawing.setClipUrl,_this._hasClipOnAxisFalse?null:_this.clipIds.forTraces,_this.gd);layers.bg.attr('d',dPath).attr('transform',strTranslate(cx,cy)).call(Color.fill,polarLayout.bgcolor);};proto.mockAxis=function(fullLayout,polarLayout,axLayout,opts){var ax=Lib.extendFlat({},axLayout,opts);setConvertPolar(ax,polarLayout,fullLayout);return ax;};proto.mockCartesianAxis=function(fullLayout,polarLayout,opts){var _this=this;var axId=opts._id;var ax=Lib.extendFlat({type:'linear'},opts);setConvertCartesian(ax,fullLayout);var bboxIndices={x:[0,2],y:[1,3]};ax.setRange=function(){var sectorBBox=_this.sectorBBox;var ind=bboxIndices[axId];var rl=_this.radialAxis._rl;var drl=(rl[1]-rl[0])/(1-polarLayout.hole);ax.range=[sectorBBox[ind[0]]*drl,sectorBBox[ind[1]]*drl];};ax.isPtWithinRange=axId==='x'?function(d){return _this.isPtInside(d);}:function(){return true;};ax.setRange();ax.setScale();return ax;};proto.doAutoRange=function(fullLayout,polarLayout){var gd=this.gd;var radialAxis=this.radialAxis;var radialLayout=polarLayout.radialaxis;radialAxis.setScale();doAutoRange(gd,radialAxis);var rng=radialAxis.range;radialLayout.range=rng.slice();radialLayout._input.range=rng.slice();radialAxis._rl=[radialAxis.r2l(rng[0],null,'gregorian'),radialAxis.r2l(rng[1],null,'gregorian')];};proto.updateRadialAxis=function(fullLayout,polarLayout){var _this=this;var gd=_this.gd;var layers=_this.layers;var radius=_this.radius;var innerRadius=_this.innerRadius;var cx=_this.cx;var cy=_this.cy;var radialLayout=polarLayout.radialaxis;var a0=mod(polarLayout.sector[0],360);var ax=_this.radialAxis;var hasRoomForIt=innerRadius90&&a0<=270){ax.tickangle=180;}// easier to set rotate angle with custom translate function\nvar transFn=function(d){return'translate('+(ax.l2p(d.x)+innerRadius)+',0)';};// set special grid path function\nvar gridPathFn=function(d){return _this.pathArc(ax.r2p(d.x)+innerRadius);};var newTickLayout=strTickLayout(radialLayout);if(_this.radialTickLayout!==newTickLayout){layers['radial-axis'].selectAll('.xtick').remove();_this.radialTickLayout=newTickLayout;}if(hasRoomForIt){ax.setScale();var vals=Axes.calcTicks(ax);var valsClipped=Axes.clipEnds(ax,vals);var tickSign=Axes.getTickSigns(ax)[2];Axes.drawTicks(gd,ax,{vals:vals,layer:layers['radial-axis'],path:Axes.makeTickPath(ax,0,tickSign),transFn:transFn,crisp:false});Axes.drawGrid(gd,ax,{vals:valsClipped,layer:layers['radial-grid'],path:gridPathFn,transFn:Lib.noop,crisp:false});Axes.drawLabels(gd,ax,{vals:vals,layer:layers['radial-axis'],transFn:transFn,labelFns:Axes.makeLabelFns(ax,0)});}// stash 'actual' radial axis angle for drag handlers (in degrees)\nvar angle=_this.radialAxisAngle=_this.vangles?rad2deg(snapToVertexAngle(deg2rad(radialLayout.angle),_this.vangles)):radialLayout.angle;var tLayer=strTranslate(cx,cy);var tLayer2=tLayer+strRotate(-angle);updateElement(layers['radial-axis'],hasRoomForIt&&(radialLayout.showticklabels||radialLayout.ticks),{transform:tLayer2});updateElement(layers['radial-grid'],hasRoomForIt&&radialLayout.showgrid,{transform:tLayer});updateElement(layers['radial-line'].select('line'),hasRoomForIt&&radialLayout.showline,{x1:innerRadius,y1:0,x2:radius,y2:0,transform:tLayer2}).attr('stroke-width',radialLayout.linewidth).call(Color.stroke,radialLayout.linecolor);};proto.updateRadialAxisTitle=function(fullLayout,polarLayout,_angle){var _this=this;var gd=_this.gd;var radius=_this.radius;var cx=_this.cx;var cy=_this.cy;var radialLayout=polarLayout.radialaxis;var titleClass=_this.id+'title';var angle=_angle!==undefined?_angle:_this.radialAxisAngle;var angleRad=deg2rad(angle);var cosa=Math.cos(angleRad);var sina=Math.sin(angleRad);var pad=0;// Hint: no need to check if there is in fact a title.text set\n// because if plot is editable, pad needs to be calculated anyways\n// to properly show placeholder text when title is empty.\nif(radialLayout.title){var h=Drawing.bBox(_this.layers['radial-axis'].node()).height;var ts=radialLayout.title.font.size;pad=radialLayout.side==='counterclockwise'?-h-ts*0.4:h+ts*0.8;}_this.layers['radial-axis-title']=Titles.draw(gd,titleClass,{propContainer:radialLayout,propName:_this.id+'.radialaxis.title',placeholder:_(gd,'Click to enter radial axis title'),attributes:{x:cx+radius/2*cosa+pad*sina,y:cy-radius/2*sina+pad*cosa,'text-anchor':'middle'},transform:{rotate:-angle}});};proto.updateAngularAxis=function(fullLayout,polarLayout){var _this=this;var gd=_this.gd;var layers=_this.layers;var radius=_this.radius;var innerRadius=_this.innerRadius;var cx=_this.cx;var cy=_this.cy;var angularLayout=polarLayout.angularaxis;var ax=_this.angularAxis;_this.fillViewInitialKey('angularaxis.rotation',angularLayout.rotation);ax.setGeometry();ax.setScale();// 't'ick to 'g'eometric radians is used all over the place here\nvar t2g=function(d){return ax.t2g(d.x);};// run rad2deg on tick0 and ditck for thetaunit: 'radians' axes\nif(ax.type==='linear'&&ax.thetaunit==='radians'){ax.tick0=rad2deg(ax.tick0);ax.dtick=rad2deg(ax.dtick);}var _transFn=function(rad){return strTranslate(cx+radius*Math.cos(rad),cy-radius*Math.sin(rad));};var transFn=function(d){return _transFn(t2g(d));};var transFn2=function(d){var rad=t2g(d);return _transFn(rad)+strRotate(-rad2deg(rad));};var gridPathFn=function(d){var rad=t2g(d);var cosRad=Math.cos(rad);var sinRad=Math.sin(rad);return'M'+[cx+innerRadius*cosRad,cy-innerRadius*sinRad]+'L'+[cx+radius*cosRad,cy-radius*sinRad];};var out=Axes.makeLabelFns(ax,0);var labelStandoff=out.labelStandoff;var labelFns={};labelFns.xFn=function(d){var rad=t2g(d);return Math.cos(rad)*labelStandoff;};labelFns.yFn=function(d){var rad=t2g(d);var ff=Math.sin(rad)>0?0.2:1;return-Math.sin(rad)*(labelStandoff+d.fontSize*ff)+Math.abs(Math.cos(rad))*(d.fontSize*MID_SHIFT);};labelFns.anchorFn=function(d){var rad=t2g(d);var cos=Math.cos(rad);return Math.abs(cos)<0.1?'middle':cos>0?'start':'end';};labelFns.heightFn=function(d,a,h){var rad=t2g(d);return-0.5*(1+Math.sin(rad))*h;};var newTickLayout=strTickLayout(angularLayout);if(_this.angularTickLayout!==newTickLayout){layers['angular-axis'].selectAll('.'+ax._id+'tick').remove();_this.angularTickLayout=newTickLayout;}var vals=Axes.calcTicks(ax);// angle of polygon vertices in geometric radians (null means circles)\n// TODO what to do when ax.period > ax._categories ??\nvar vangles;if(polarLayout.gridshape==='linear'){vangles=vals.map(t2g);// ax._vals should be always ordered, make them\n// always turn counterclockwise for convenience here\nif(Lib.angleDelta(vangles[0],vangles[1])<0){vangles=vangles.slice().reverse();}}else{vangles=null;}_this.vangles=vangles;// Use tickval filter for category axes instead of tweaking\n// the range w.r.t sector, so that sectors that cross 360 can\n// show all their ticks.\nif(ax.type==='category'){vals=vals.filter(function(d){return Lib.isAngleInsideSector(t2g(d),_this.sectorInRad);});}if(ax.visible){var tickSign=ax.ticks==='inside'?-1:1;var pad=(ax.linewidth||1)/2;Axes.drawTicks(gd,ax,{vals:vals,layer:layers['angular-axis'],path:'M'+tickSign*pad+',0h'+tickSign*ax.ticklen,transFn:transFn2,crisp:false});Axes.drawGrid(gd,ax,{vals:vals,layer:layers['angular-grid'],path:gridPathFn,transFn:Lib.noop,crisp:false});Axes.drawLabels(gd,ax,{vals:vals,layer:layers['angular-axis'],repositionOnUpdate:true,transFn:transFn,labelFns:labelFns});}// TODO maybe two arcs is better here?\n// maybe split style attributes between inner and outer angular axes?\nupdateElement(layers['angular-line'].select('path'),angularLayout.showline,{d:_this.pathSubplot(),transform:strTranslate(cx,cy)}).attr('stroke-width',angularLayout.linewidth).call(Color.stroke,angularLayout.linecolor);};proto.updateFx=function(fullLayout,polarLayout){if(!this.gd._context.staticPlot){this.updateAngularDrag(fullLayout);this.updateRadialDrag(fullLayout,polarLayout,0);this.updateRadialDrag(fullLayout,polarLayout,1);this.updateMainDrag(fullLayout);}};proto.updateMainDrag=function(fullLayout){var _this=this;var gd=_this.gd;var layers=_this.layers;var zoomlayer=fullLayout._zoomlayer;var MINZOOM=constants.MINZOOM;var OFFEDGE=constants.OFFEDGE;var radius=_this.radius;var innerRadius=_this.innerRadius;var cx=_this.cx;var cy=_this.cy;var cxx=_this.cxx;var cyy=_this.cyy;var sectorInRad=_this.sectorInRad;var vangles=_this.vangles;var radialAxis=_this.radialAxis;var clampTiny=helpers.clampTiny;var findXYatLength=helpers.findXYatLength;var findEnclosingVertexAngles=helpers.findEnclosingVertexAngles;var chw=constants.cornerHalfWidth;var chl=constants.cornerLen/2;var mainDrag=dragBox.makeDragger(layers,'path','maindrag','crosshair');d3.select(mainDrag).attr('d',_this.pathSubplot()).attr('transform',strTranslate(cx,cy));var dragOpts={element:mainDrag,gd:gd,subplot:_this.id,plotinfo:{id:_this.id,xaxis:_this.xaxis,yaxis:_this.yaxis},xaxes:[_this.xaxis],yaxes:[_this.yaxis]};// mouse px position at drag start (0), move (1)\nvar x0,y0;// radial distance from circle center at drag start (0), move (1)\nvar r0,r1;// zoombox persistent quantities\nvar path0,dimmed,lum;// zoombox, corners elements\nvar zb,corners;function norm(x,y){return Math.sqrt(x*x+y*y);}function xy2r(x,y){return norm(x-cxx,y-cyy);}function xy2a(x,y){return Math.atan2(cyy-y,x-cxx);}function ra2xy(r,a){return[r*Math.cos(a),r*Math.sin(-a)];}function pathCorner(r,a){if(r===0)return _this.pathSector(2*chw);var da=chl/r;var am=a-da;var ap=a+da;var rb=Math.max(0,Math.min(r,radius));var rm=rb-chw;var rp=rb+chw;return'M'+ra2xy(rm,am)+'A'+[rm,rm]+' 0,0,0 '+ra2xy(rm,ap)+'L'+ra2xy(rp,ap)+'A'+[rp,rp]+' 0,0,1 '+ra2xy(rp,am)+'Z';}// (x,y) is the pt at middle of the va0 <-> va1 edge\n//\n// ... we could eventually add another mode for cursor\n// angles 'close to' enough to a particular vertex.\nfunction pathCornerForPolygons(r,va0,va1){if(r===0)return _this.pathSector(2*chw);var xy0=ra2xy(r,va0);var xy1=ra2xy(r,va1);var x=clampTiny((xy0[0]+xy1[0])/2);var y=clampTiny((xy0[1]+xy1[1])/2);var innerPts,outerPts;if(x&&y){var m=y/x;var mperp=-1/m;var midPts=findXYatLength(chw,m,x,y);innerPts=findXYatLength(chl,mperp,midPts[0][0],midPts[0][1]);outerPts=findXYatLength(chl,mperp,midPts[1][0],midPts[1][1]);}else{var dx,dy;if(y){// horizontal handles\ndx=chl;dy=chw;}else{// vertical handles\ndx=chw;dy=chl;}innerPts=[[x-dx,y-dy],[x+dx,y-dy]];outerPts=[[x-dx,y+dy],[x+dx,y+dy]];}return'M'+innerPts.join('L')+'L'+outerPts.reverse().join('L')+'Z';}function zoomPrep(){r0=null;r1=null;path0=_this.pathSubplot();dimmed=false;var polarLayoutNow=gd._fullLayout[_this.id];lum=tinycolor(polarLayoutNow.bgcolor).getLuminance();zb=dragBox.makeZoombox(zoomlayer,lum,cx,cy,path0);zb.attr('fill-rule','evenodd');corners=dragBox.makeCorners(zoomlayer,cx,cy);clearSelect(gd);}// N.B. this sets scoped 'r0' and 'r1'\n// return true if 'valid' zoom distance, false otherwise\nfunction clampAndSetR0R1(rr0,rr1){rr1=Math.max(Math.min(rr1,radius),innerRadius);// starting or ending drag near center (outer edge),\n// clamps radial distance at origin (at r=radius)\nif(rr0MINZOOM){if(rr0-1&&numClicks===1){selectOnClick(evt,gd,[_this.xaxis],[_this.yaxis],_this.id,dragOpts);}if(clickMode.indexOf('event')>-1){Fx.click(gd,evt,_this.id);}}dragOpts.prepFn=function(evt,startX,startY){var dragModeNow=gd._fullLayout.dragmode;var bbox=mainDrag.getBoundingClientRect();x0=startX-bbox.left;y0=startY-bbox.top;// need to offset x/y as bbox center does not\n// match origin for asymmetric polygons\nif(vangles){var offset=helpers.findPolygonOffset(radius,sectorInRad[0],sectorInRad[1],vangles);x0+=cxx+offset[0];y0+=cyy+offset[1];}switch(dragModeNow){case'zoom':if(vangles){dragOpts.moveFn=zoomMoveForPolygons;}else{dragOpts.moveFn=zoomMove;}dragOpts.clickFn=zoomClick;dragOpts.doneFn=zoomDone;zoomPrep(evt,startX,startY);break;case'select':case'lasso':prepSelect(evt,startX,startY,dragOpts,dragModeNow);break;}};mainDrag.onmousemove=function(evt){Fx.hover(gd,evt,_this.id);gd._fullLayout._lasthover=mainDrag;gd._fullLayout._hoversubplot=_this.id;};mainDrag.onmouseout=function(evt){if(gd._dragging)return;dragElement.unhover(gd,evt);};dragElement.init(dragOpts);};proto.updateRadialDrag=function(fullLayout,polarLayout,rngIndex){var _this=this;var gd=_this.gd;var layers=_this.layers;var radius=_this.radius;var innerRadius=_this.innerRadius;var cx=_this.cx;var cy=_this.cy;var radialAxis=_this.radialAxis;var bl=constants.radialDragBoxSize;var bl2=bl/2;if(!radialAxis.visible)return;var angle0=deg2rad(_this.radialAxisAngle);var rl=radialAxis._rl;var rl0=rl[0];var rl1=rl[1];var rbase=rl[rngIndex];var m=0.75*(rl[1]-rl[0])/(1-polarLayout.hole)/radius;var tx,ty,className;if(rngIndex){tx=cx+(radius+bl2)*Math.cos(angle0);ty=cy-(radius+bl2)*Math.sin(angle0);className='radialdrag';}else{// the 'inner' box can get called:\n// - when polar.hole>0\n// - when polar.sector isn't a full circle\n// otherwise it is hidden behind the main drag.\ntx=cx+(innerRadius-bl2)*Math.cos(angle0);ty=cy-(innerRadius-bl2)*Math.sin(angle0);className='radialdrag-inner';}var radialDrag=dragBox.makeRectDragger(layers,className,'crosshair',-bl2,-bl2,bl,bl);var dragOpts={element:radialDrag,gd:gd};updateElement(d3.select(radialDrag),radialAxis.visible&&innerRadius range[1] sign\nif(m>0!==(rngIndex?rprime>rl0:rprime update c2g -> update _m,_b\nradialAxis.range[rngIndex]=rprime;radialAxis._rl[rngIndex]=rprime;_this.updateRadialAxis(fullLayoutNow,polarLayoutNow);_this.xaxis.setRange();_this.xaxis.setScale();_this.yaxis.setRange();_this.yaxis.setScale();var hasRegl=false;for(var traceType in _this.traceHash){var moduleCalcData=_this.traceHash[traceType];var moduleCalcDataVisible=Lib.filterVisible(moduleCalcData);var _module=moduleCalcData[0][0].trace._module;_module.plot(gd,_this,moduleCalcDataVisible,polarLayoutNow);if(Registry.traceIs(traceType,'gl')&&moduleCalcDataVisible.length)hasRegl=true;}if(hasRegl){clearGlCanvases(gd);redrawReglTraces(gd);}}dragOpts.prepFn=function(){moveFn2=null;angle1=null;rprime=null;dragOpts.moveFn=moveFn;dragOpts.doneFn=doneFn;clearSelect(gd);};dragOpts.clampFn=function(dx,dy){if(Math.sqrt(dx*dx+dy*dy) translate ordering matters\nsel.attr('transform',strRotate([da,tx.attr('x'),tx.attr('y')])+strTranslate(xy.x,xy.y));});// update rotation -> range -> _m,_b\nangularAxis.rotation=Lib.modHalf(rot1,360);_this.updateAngularAxis(fullLayoutNow,polarLayoutNow);if(_this._hasClipOnAxisFalse&&!Lib.isFullCircle(_this.sectorInRad)){scatterTraces.call(Drawing.hideOutsideRangePoints,_this);}var hasRegl=false;for(var traceType in _this.traceHash){if(Registry.traceIs(traceType,'gl')){var moduleCalcData=_this.traceHash[traceType];var moduleCalcDataVisible=Lib.filterVisible(moduleCalcData);var _module=moduleCalcData[0][0].trace._module;_module.plot(gd,_this,moduleCalcDataVisible,polarLayoutNow);if(moduleCalcDataVisible.length)hasRegl=true;}}if(hasRegl){clearGlCanvases(gd);redrawReglTraces(gd);}var update={};computeRotationUpdates(update);gd.emit('plotly_relayouting',update);}function computeRotationUpdates(updateObj){updateObj[_this.id+'.angularaxis.rotation']=rot1;if(_this.vangles){updateObj[_this.id+'.radialaxis.angle']=rrot1;}}function doneFn(){scatterTextPoints.select('text').attr('transform',null);var updateObj={};computeRotationUpdates(updateObj);Registry.call('_guiRelayout',gd,updateObj);}dragOpts.prepFn=function(evt,startX,startY){var polarLayoutNow=fullLayout[_this.id];rot0=polarLayoutNow.angularaxis.rotation;var bbox=angularDrag.getBoundingClientRect();x0=startX-bbox.left;y0=startY-bbox.top;a0=xy2a(x0,y0);dragOpts.moveFn=moveFn;dragOpts.doneFn=doneFn;clearSelect(gd);};// I don't what we should do in this case, skip we now\nif(_this.vangles&&!Lib.isFullCircle(_this.sectorInRad)){dragOpts.prepFn=Lib.noop;setCursor(d3.select(angularDrag),null);}dragElement.init(dragOpts);};proto.isPtInside=function(d){var sectorInRad=this.sectorInRad;var vangles=this.vangles;var thetag=this.angularAxis.c2g(d.theta);var radialAxis=this.radialAxis;var r=radialAxis.c2l(d.r);var rl=radialAxis._rl;var fn=vangles?helpers.isPtInsidePolygon:Lib.isPtInsideSector;return fn(r,thetag,rl,sectorInRad,vangles);};proto.pathArc=function(r){var sectorInRad=this.sectorInRad;var vangles=this.vangles;var fn=vangles?helpers.pathPolygon:Lib.pathArc;return fn(r,sectorInRad[0],sectorInRad[1],vangles);};proto.pathSector=function(r){var sectorInRad=this.sectorInRad;var vangles=this.vangles;var fn=vangles?helpers.pathPolygon:Lib.pathSector;return fn(r,sectorInRad[0],sectorInRad[1],vangles);};proto.pathAnnulus=function(r0,r1){var sectorInRad=this.sectorInRad;var vangles=this.vangles;var fn=vangles?helpers.pathPolygonAnnulus:Lib.pathAnnulus;return fn(r0,r1,sectorInRad[0],sectorInRad[1],vangles);};proto.pathSubplot=function(){var r0=this.innerRadius;var r1=this.radius;return r0?this.pathAnnulus(r0,r1):this.pathSector(r1);};proto.fillViewInitialKey=function(key,val){if(!(key in this.viewInitial)){this.viewInitial[key]=val;}};function strTickLayout(axLayout){var out=axLayout.ticks+String(axLayout.ticklen)+String(axLayout.showticklabels);if('side'in axLayout)out+=axLayout.side;return out;}// Finds the bounding box of a given circle sector,\n// inspired by https://math.stackexchange.com/q/1852703\n//\n// assumes:\n// - sector[0] < sector[1]\n// - counterclockwise rotation\nfunction computeSectorBBox(sector){var s0=sector[0];var s1=sector[1];var arc=s1-s0;var a0=mod(s0,360);var a1=a0+arc;var ax0=Math.cos(deg2rad(a0));var ay0=Math.sin(deg2rad(a0));var ax1=Math.cos(deg2rad(a1));var ay1=Math.sin(deg2rad(a1));var x0,y0,x1,y1;if(a0<=90&&a1>=90||a0>90&&a1>=450){y1=1;}else if(ay0<=0&&ay1<=0){y1=0;}else{y1=Math.max(ay0,ay1);}if(a0<=180&&a1>=180||a0>180&&a1>=540){x0=-1;}else if(ax0>=0&&ax1>=0){x0=0;}else{x0=Math.min(ax0,ax1);}if(a0<=270&&a1>=270||a0>270&&a1>=630){y0=-1;}else if(ay0>=0&&ay1>=0){y0=0;}else{y0=Math.min(ay0,ay1);}if(a1>=360){x1=1;}else if(ax0<=0&&ax1<=0){x1=0;}else{x1=Math.max(ax0,ax1);}return[x0,y0,x1,y1];}function snapToVertexAngle(a,vangles){var fn=function(v){return Lib.angleDist(a,v);};var ind=Lib.findIndexOfMin(vangles,fn);return vangles[ind];}function updateElement(sel,showAttr,attrs){if(showAttr){sel.attr('display',null);sel.attr(attrs);}else if(sel){sel.attr('display','none');}return sel;}function strTranslate(x,y){return'translate('+x+','+y+')';}function strRotate(angle){return'rotate('+angle+')';}},{\"../../components/color\":602,\"../../components/dragelement\":621,\"../../components/drawing\":624,\"../../components/fx\":642,\"../../components/titles\":697,\"../../constants/alignment\":704,\"../../lib\":735,\"../../lib/clear_gl_canvases\":720,\"../../lib/setcursor\":755,\"../../plot_api/subroutines\":774,\"../../plots/cartesian/axes\":783,\"../../registry\":866,\"../cartesian/autorange\":782,\"../cartesian/dragbox\":791,\"../cartesian/select\":802,\"../cartesian/set_convert\":803,\"../plots\":846,\"./constants\":847,\"./helpers\":848,\"./set_convert\":859,\"d3\":165,\"tinycolor2\":535}],859:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Lib=_dereq_('../../lib');var setConvertCartesian=_dereq_('../cartesian/set_convert');var deg2rad=Lib.deg2rad;var rad2deg=Lib.rad2deg;/**\n * setConvert for polar axes!\n *\n * @param {object} ax\n * axis in question (works for both radial and angular axes)\n * @param {object} polarLayout\n * full polar layout of the subplot associated with 'ax'\n * @param {object} fullLayout\n * full layout\n *\n * Here, reuse some of the Cartesian setConvert logic,\n * but we must extend some of it, as both radial and angular axes\n * don't have domains and angular axes don't have _true_ ranges.\n *\n * Moreover, we introduce two new coordinate systems:\n * - 'g' for geometric coordinates and\n * - 't' for angular ticks\n *\n * Radial axis coordinate systems:\n * - d, c and l: same as for cartesian axes\n * - g: like calcdata but translated about `radialaxis.range[0]` & `polar.hole`\n *\n * Angular axis coordinate systems:\n * - d: data, in whatever form it's provided\n * - c: calcdata, turned into radians (for linear axes)\n * or category indices (category axes)\n * - t: tick calcdata, just like 'c' but in degrees for linear axes\n * - g: geometric calcdata, radians coordinates that take into account\n * axis rotation and direction\n *\n * Then, 'g'eometric data is ready to be converted to (x,y).\n */module.exports=function setConvert(ax,polarLayout,fullLayout){setConvertCartesian(ax,fullLayout);switch(ax._id){case'x':case'radialaxis':setConvertRadial(ax,polarLayout);break;case'angularaxis':setConvertAngular(ax,polarLayout);break;}};function setConvertRadial(ax,polarLayout){var subplot=polarLayout._subplot;ax.setGeometry=function(){var rl0=ax._rl[0];var rl1=ax._rl[1];var b=subplot.innerRadius;var m=(subplot.radius-b)/(rl1-rl0);var b2=b/m;var rFilter=rl0>rl1?function(v){return v<=0;}:function(v){return v>=0;};ax.c2g=function(v){var r=ax.c2l(v)-rl0;return(rFilter(r)?r:0)+b2;};ax.g2c=function(v){return ax.l2c(v+rl0-b2);};ax.g2p=function(v){return v*m;};ax.c2p=function(v){return ax.g2p(ax.c2g(v));};};}function toRadians(v,unit){return unit==='degrees'?deg2rad(v):v;}function fromRadians(v,unit){return unit==='degrees'?rad2deg(v):v;}function setConvertAngular(ax,polarLayout){var axType=ax.type;if(axType==='linear'){var _d2c=ax.d2c;var _c2d=ax.c2d;ax.d2c=function(v,unit){return toRadians(_d2c(v),unit);};ax.c2d=function(v,unit){return _c2d(fromRadians(v,unit));};}// override makeCalcdata to handle thetaunit and special theta0/dtheta logic\nax.makeCalcdata=function(trace,coord){var arrayIn=trace[coord];var len=trace._length;var arrayOut,i;var _d2c=function(v){return ax.d2c(v,trace.thetaunit);};if(arrayIn){if(Lib.isTypedArray(arrayIn)&&axType==='linear'){if(len===arrayIn.length){return arrayIn;}else if(arrayIn.subarray){return arrayIn.subarray(0,len);}}arrayOut=new Array(len);for(i=0;i0){var quotedKeys=[];for(var i=0;i=sum){aaxis.min=0;baxis.min=0;caxis.min=0;if(ternaryLayoutIn.aaxis)delete ternaryLayoutIn.aaxis.min;if(ternaryLayoutIn.baxis)delete ternaryLayoutIn.baxis.min;if(ternaryLayoutIn.caxis)delete ternaryLayoutIn.caxis.min;}}function handleAxisDefaults(containerIn,containerOut,options,ternaryLayoutOut){var axAttrs=layoutAttributes[containerOut._name];function coerce(attr,dflt){return Lib.coerce(containerIn,containerOut,axAttrs,attr,dflt);}coerce('uirevision',ternaryLayoutOut.uirevision);containerOut.type='linear';// no other types allowed for ternary\nvar dfltColor=coerce('color');// if axis.color was provided, use it for fonts too; otherwise,\n// inherit from global font color in case that was provided.\nvar dfltFontColor=dfltColor!==axAttrs.color.dflt?dfltColor:options.font.color;var axName=containerOut._name;var letterUpper=axName.charAt(0).toUpperCase();var dfltTitle='Component '+letterUpper;var title=coerce('title.text',dfltTitle);containerOut._hovertitle=title===dfltTitle?title:letterUpper;Lib.coerceFont(coerce,'title.font',{family:options.font.family,size:Math.round(options.font.size*1.2),color:dfltFontColor});// range is just set by 'min' - max is determined by the other axes mins\ncoerce('min');handleTickValueDefaults(containerIn,containerOut,coerce,'linear');handleTickLabelDefaults(containerIn,containerOut,coerce,'linear',{});handleTickMarkDefaults(containerIn,containerOut,coerce,{outerTicks:true});var showTickLabels=coerce('showticklabels');if(showTickLabels){Lib.coerceFont(coerce,'tickfont',{family:options.font.family,size:options.font.size,color:dfltFontColor});coerce('tickangle');coerce('tickformat');}handleLineGridDefaults(containerIn,containerOut,coerce,{dfltColor:dfltColor,bgColor:options.bgColor,// default grid color is darker here (60%, vs cartesian default ~91%)\n// because the grid is not square so the eye needs heavier cues to follow\nblend:60,showLine:true,showGrid:true,noZeroLine:true,attributes:axAttrs});coerce('hoverformat');coerce('layer');}},{\"../../components/color\":602,\"../../lib\":735,\"../../plot_api/plot_template\":773,\"../cartesian/line_grid_defaults\":799,\"../cartesian/tick_label_defaults\":804,\"../cartesian/tick_mark_defaults\":805,\"../cartesian/tick_value_defaults\":806,\"../subplot_defaults\":860,\"./layout_attributes\":863}],865:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var d3=_dereq_('d3');var tinycolor=_dereq_('tinycolor2');var Registry=_dereq_('../../registry');var Lib=_dereq_('../../lib');var _=Lib._;var Color=_dereq_('../../components/color');var Drawing=_dereq_('../../components/drawing');var setConvert=_dereq_('../cartesian/set_convert');var extendFlat=_dereq_('../../lib/extend').extendFlat;var Plots=_dereq_('../plots');var Axes=_dereq_('../cartesian/axes');var dragElement=_dereq_('../../components/dragelement');var Fx=_dereq_('../../components/fx');var dragHelpers=_dereq_('../../components/dragelement/helpers');var freeMode=dragHelpers.freeMode;var rectMode=dragHelpers.rectMode;var Titles=_dereq_('../../components/titles');var prepSelect=_dereq_('../cartesian/select').prepSelect;var selectOnClick=_dereq_('../cartesian/select').selectOnClick;var clearSelect=_dereq_('../cartesian/select').clearSelect;var clearSelectionsCache=_dereq_('../cartesian/select').clearSelectionsCache;var constants=_dereq_('../cartesian/constants');function Ternary(options,fullLayout){this.id=options.id;this.graphDiv=options.graphDiv;this.init(fullLayout);this.makeFramework(fullLayout);// unfortunately, we have to keep track of some axis tick settings\n// as ternary subplots do not implement the 'ticks' editType\nthis.aTickLayout=null;this.bTickLayout=null;this.cTickLayout=null;}module.exports=Ternary;var proto=Ternary.prototype;proto.init=function(fullLayout){this.container=fullLayout._ternarylayer;this.defs=fullLayout._defs;this.layoutId=fullLayout._uid;this.traceHash={};this.layers={};};proto.plot=function(ternaryCalcData,fullLayout){var _this=this;var ternaryLayout=fullLayout[_this.id];var graphSize=fullLayout._size;_this._hasClipOnAxisFalse=false;for(var i=0;iwhRatio*hmax){h=hmax;w=h*whRatio;}else{w=wmax;h=w/whRatio;}xDomainFinal=xDomain*w/wmax;yDomainFinal=yDomain*h/hmax;x0=graphSize.l+graphSize.w*xDomainCenter-w/2;y0=graphSize.t+graphSize.h*(1-yDomainCenter)-h/2;_this.x0=x0;_this.y0=y0;_this.w=w;_this.h=h;_this.sum=sum;// set up the x and y axis objects we'll use to lay out the points\n_this.xaxis={type:'linear',range:[amin+2*cmin-sum,sum-amin-2*bmin],domain:[xDomainCenter-xDomainFinal/2,xDomainCenter+xDomainFinal/2],_id:'x'};setConvert(_this.xaxis,_this.graphDiv._fullLayout);_this.xaxis.setScale();_this.xaxis.isPtWithinRange=function(d){return d.a>=_this.aaxis.range[0]&&d.a<=_this.aaxis.range[1]&&d.b>=_this.baxis.range[1]&&d.b<=_this.baxis.range[0]&&d.c>=_this.caxis.range[1]&&d.c<=_this.caxis.range[0];};_this.yaxis={type:'linear',range:[amin,sum-bmin-cmin],domain:[yDomainCenter-yDomainFinal/2,yDomainCenter+yDomainFinal/2],_id:'y'};setConvert(_this.yaxis,_this.graphDiv._fullLayout);_this.yaxis.setScale();_this.yaxis.isPtWithinRange=function(){return true;};// set up the modified axes for tick drawing\nvar yDomain0=_this.yaxis.domain[0];// aaxis goes up the left side. Set it up as a y axis, but with\n// fictitious angles and domain, but then rotate and translate\n// it into place at the end\nvar aaxis=_this.aaxis=extendFlat({},ternaryLayout.aaxis,{range:[amin,sum-bmin-cmin],side:'left',// tickangle = 'auto' means 0 anyway for a y axis, need to coerce to 0 here\n// so we can shift by 30.\ntickangle:(+ternaryLayout.aaxis.tickangle||0)-30,domain:[yDomain0,yDomain0+yDomainFinal*whRatio],anchor:'free',position:0,_id:'y',_length:w});setConvert(aaxis,_this.graphDiv._fullLayout);aaxis.setScale();// baxis goes across the bottom (backward). We can set it up as an x axis\n// without any enclosing transformation.\nvar baxis=_this.baxis=extendFlat({},ternaryLayout.baxis,{range:[sum-amin-cmin,bmin],side:'bottom',domain:_this.xaxis.domain,anchor:'free',position:0,_id:'x',_length:w});setConvert(baxis,_this.graphDiv._fullLayout);baxis.setScale();// caxis goes down the right side. Set it up as a y axis, with\n// post-transformation similar to aaxis\nvar caxis=_this.caxis=extendFlat({},ternaryLayout.caxis,{range:[sum-amin-bmin,cmin],side:'right',tickangle:(+ternaryLayout.caxis.tickangle||0)+30,domain:[yDomain0,yDomain0+yDomainFinal*whRatio],anchor:'free',position:0,_id:'y',_length:w});setConvert(caxis,_this.graphDiv._fullLayout);caxis.setScale();var triangleClip='M'+x0+','+(y0+h)+'h'+w+'l-'+w/2+',-'+h+'Z';_this.clipDef.select('path').attr('d',triangleClip);_this.layers.plotbg.select('path').attr('d',triangleClip);var triangleClipRelative='M0,'+h+'h'+w+'l-'+w/2+',-'+h+'Z';_this.clipDefRelative.select('path').attr('d',triangleClipRelative);var plotTransform='translate('+x0+','+y0+')';_this.plotContainer.selectAll('.scatterlayer,.maplayer').attr('transform',plotTransform);_this.clipDefRelative.select('path').attr('transform',null);// TODO: shift axes to accommodate linewidth*sin(30) tick mark angle\n// TODO: there's probably an easier way to handle these translations/offsets now...\nvar bTransform='translate('+(x0-baxis._offset)+','+(y0+h)+')';_this.layers.baxis.attr('transform',bTransform);_this.layers.bgrid.attr('transform',bTransform);var aTransform='translate('+(x0+w/2)+','+y0+')rotate(30)translate(0,'+-aaxis._offset+')';_this.layers.aaxis.attr('transform',aTransform);_this.layers.agrid.attr('transform',aTransform);var cTransform='translate('+(x0+w/2)+','+y0+')rotate(-30)translate(0,'+-caxis._offset+')';_this.layers.caxis.attr('transform',cTransform);_this.layers.cgrid.attr('transform',cTransform);_this.drawAxes(true);_this.layers.aline.select('path').attr('d',aaxis.showline?'M'+x0+','+(y0+h)+'l'+w/2+',-'+h:'M0,0').call(Color.stroke,aaxis.linecolor||'#000').style('stroke-width',(aaxis.linewidth||0)+'px');_this.layers.bline.select('path').attr('d',baxis.showline?'M'+x0+','+(y0+h)+'h'+w:'M0,0').call(Color.stroke,baxis.linecolor||'#000').style('stroke-width',(baxis.linewidth||0)+'px');_this.layers.cline.select('path').attr('d',caxis.showline?'M'+(x0+w/2)+','+y0+'l'+w/2+','+h:'M0,0').call(Color.stroke,caxis.linecolor||'#000').style('stroke-width',(caxis.linewidth||0)+'px');if(!_this.graphDiv._context.staticPlot){_this.initInteractions();}Drawing.setClipUrl(_this.layers.frontplot,_this._hasClipOnAxisFalse?null:_this.clipId,_this.graphDiv);};proto.drawAxes=function(doTitles){var _this=this;var gd=_this.graphDiv;var titlesuffix=_this.id.substr(7)+'title';var layers=_this.layers;var aaxis=_this.aaxis;var baxis=_this.baxis;var caxis=_this.caxis;_this.drawAx(aaxis);_this.drawAx(baxis);_this.drawAx(caxis);if(doTitles){var apad=Math.max(aaxis.showticklabels?aaxis.tickfont.size/2:0,(caxis.showticklabels?caxis.tickfont.size*0.75:0)+(caxis.ticks==='outside'?caxis.ticklen*0.87:0));var bpad=(baxis.showticklabels?baxis.tickfont.size:0)+(baxis.ticks==='outside'?baxis.ticklen:0)+3;layers['a-title']=Titles.draw(gd,'a'+titlesuffix,{propContainer:aaxis,propName:_this.id+'.aaxis.title',placeholder:_(gd,'Click to enter Component A title'),attributes:{x:_this.x0+_this.w/2,y:_this.y0-aaxis.title.font.size/3-apad,'text-anchor':'middle'}});layers['b-title']=Titles.draw(gd,'b'+titlesuffix,{propContainer:baxis,propName:_this.id+'.baxis.title',placeholder:_(gd,'Click to enter Component B title'),attributes:{x:_this.x0-bpad,y:_this.y0+_this.h+baxis.title.font.size*0.83+bpad,'text-anchor':'middle'}});layers['c-title']=Titles.draw(gd,'c'+titlesuffix,{propContainer:caxis,propName:_this.id+'.caxis.title',placeholder:_(gd,'Click to enter Component C title'),attributes:{x:_this.x0+_this.w+bpad,y:_this.y0+_this.h+caxis.title.font.size*0.83+bpad,'text-anchor':'middle'}});}};proto.drawAx=function(ax){var _this=this;var gd=_this.graphDiv;var axName=ax._name;var axLetter=axName.charAt(0);var axId=ax._id;var axLayer=_this.layers[axName];var counterAngle=30;var stashKey=axLetter+'tickLayout';var newTickLayout=strTickLayout(ax);if(_this[stashKey]!==newTickLayout){axLayer.selectAll('.'+axId+'tick').remove();_this[stashKey]=newTickLayout;}ax.setScale();var vals=Axes.calcTicks(ax);var valsClipped=Axes.clipEnds(ax,vals);var transFn=Axes.makeTransFn(ax);var tickSign=Axes.getTickSigns(ax)[2];var caRad=Lib.deg2rad(counterAngle);var pad=tickSign*(ax.linewidth||1)/2;var len=tickSign*ax.ticklen;var w=_this.w;var h=_this.h;var tickPath=axLetter==='b'?'M0,'+pad+'l'+Math.sin(caRad)*len+','+Math.cos(caRad)*len:'M'+pad+',0l'+Math.cos(caRad)*len+','+-Math.sin(caRad)*len;var gridPath={a:'M0,0l'+h+',-'+w/2,b:'M0,0l-'+w/2+',-'+h,c:'M0,0l-'+h+','+w/2}[axLetter];Axes.drawTicks(gd,ax,{vals:ax.ticks==='inside'?valsClipped:vals,layer:axLayer,path:tickPath,transFn:transFn,crisp:false});Axes.drawGrid(gd,ax,{vals:valsClipped,layer:_this.layers[axLetter+'grid'],path:gridPath,transFn:transFn,crisp:false});Axes.drawLabels(gd,ax,{vals:vals,layer:axLayer,transFn:transFn,labelFns:Axes.makeLabelFns(ax,0,counterAngle)});};function strTickLayout(axLayout){return axLayout.ticks+String(axLayout.ticklen)+String(axLayout.showticklabels);}// hard coded paths for zoom corners\n// uses the same sizing as cartesian, length is MINZOOM/2, width is 3px\nvar CLEN=constants.MINZOOM/2+0.87;var BLPATH='m-0.87,.5h'+CLEN+'v3h-'+(CLEN+5.2)+'l'+(CLEN/2+2.6)+',-'+(CLEN*0.87+4.5)+'l2.6,1.5l-'+CLEN/2+','+CLEN*0.87+'Z';var BRPATH='m0.87,.5h-'+CLEN+'v3h'+(CLEN+5.2)+'l-'+(CLEN/2+2.6)+',-'+(CLEN*0.87+4.5)+'l-2.6,1.5l'+CLEN/2+','+CLEN*0.87+'Z';var TOPPATH='m0,1l'+CLEN/2+','+CLEN*0.87+'l2.6,-1.5l-'+(CLEN/2+2.6)+',-'+(CLEN*0.87+4.5)+'l-'+(CLEN/2+2.6)+','+(CLEN*0.87+4.5)+'l2.6,1.5l'+CLEN/2+',-'+CLEN*0.87+'Z';var STARTMARKER='m0.5,0.5h5v-2h-5v-5h-2v5h-5v2h5v5h2Z';// I guess this could be shared with cartesian... but for now it's separate.\nvar SHOWZOOMOUTTIP=true;proto.clearSelect=function(){clearSelectionsCache(this.dragOptions);clearSelect(this.dragOptions.gd);};proto.initInteractions=function(){var _this=this;var dragger=_this.layers.plotbg.select('path').node();var gd=_this.graphDiv;var zoomLayer=gd._fullLayout._zoomlayer;// use plotbg for the main interactions\nthis.dragOptions={element:dragger,gd:gd,plotinfo:{id:_this.id,domain:gd._fullLayout[_this.id].domain,xaxis:_this.xaxis,yaxis:_this.yaxis},subplot:_this.id,prepFn:function(e,startX,startY){// these aren't available yet when initInteractions\n// is called\n_this.dragOptions.xaxes=[_this.xaxis];_this.dragOptions.yaxes=[_this.yaxis];var dragModeNow=_this.dragOptions.dragmode=gd._fullLayout.dragmode;if(freeMode(dragModeNow))_this.dragOptions.minDrag=1;else _this.dragOptions.minDrag=undefined;if(dragModeNow==='zoom'){_this.dragOptions.moveFn=zoomMove;_this.dragOptions.clickFn=clickZoomPan;_this.dragOptions.doneFn=zoomDone;zoomPrep(e,startX,startY);}else if(dragModeNow==='pan'){_this.dragOptions.moveFn=plotDrag;_this.dragOptions.clickFn=clickZoomPan;_this.dragOptions.doneFn=dragDone;panPrep();_this.clearSelect(gd);}else if(rectMode(dragModeNow)||freeMode(dragModeNow)){prepSelect(e,startX,startY,_this.dragOptions,dragModeNow);}}};var x0,y0,mins0,span0,mins,lum,path0,dimmed,zb,corners;function makeUpdate(_mins){var attrs={};attrs[_this.id+'.aaxis.min']=_mins.a;attrs[_this.id+'.baxis.min']=_mins.b;attrs[_this.id+'.caxis.min']=_mins.c;return attrs;}function clickZoomPan(numClicks,evt){var clickMode=gd._fullLayout.clickmode;removeZoombox(gd);if(numClicks===2){gd.emit('plotly_doubleclick',null);Registry.call('_guiRelayout',gd,makeUpdate({a:0,b:0,c:0}));}if(clickMode.indexOf('select')>-1&&numClicks===1){selectOnClick(evt,gd,[_this.xaxis],[_this.yaxis],_this.id,_this.dragOptions);}if(clickMode.indexOf('event')>-1){Fx.click(gd,evt,_this.id);}}function zoomPrep(e,startX,startY){var dragBBox=dragger.getBoundingClientRect();x0=startX-dragBBox.left;y0=startY-dragBBox.top;mins0={a:_this.aaxis.range[0],b:_this.baxis.range[1],c:_this.caxis.range[1]};mins=mins0;span0=_this.aaxis.range[1]-mins0.a;lum=tinycolor(_this.graphDiv._fullLayout[_this.id].bgcolor).getLuminance();path0='M0,'+_this.h+'L'+_this.w/2+', 0L'+_this.w+','+_this.h+'Z';dimmed=false;zb=zoomLayer.append('path').attr('class','zoombox').attr('transform','translate('+_this.x0+', '+_this.y0+')').style({'fill':lum>0.2?'rgba(0,0,0,0)':'rgba(255,255,255,0)','stroke-width':0}).attr('d',path0);corners=zoomLayer.append('path').attr('class','zoombox-corners').attr('transform','translate('+_this.x0+', '+_this.y0+')').style({fill:Color.background,stroke:Color.defaultLine,'stroke-width':1,opacity:0}).attr('d','M0,0Z');_this.clearSelect(gd);}function getAFrac(x,y){return 1-y/_this.h;}function getBFrac(x,y){return 1-(x+(_this.h-y)/Math.sqrt(3))/_this.w;}function getCFrac(x,y){return(x-(_this.h-y)/Math.sqrt(3))/_this.w;}function zoomMove(dx0,dy0){var x1=x0+dx0;var y1=y0+dy0;var afrac=Math.max(0,Math.min(1,getAFrac(x0,y0),getAFrac(x1,y1)));var bfrac=Math.max(0,Math.min(1,getBFrac(x0,y0),getBFrac(x1,y1)));var cfrac=Math.max(0,Math.min(1,getCFrac(x0,y0),getCFrac(x1,y1)));var xLeft=(afrac/2+cfrac)*_this.w;var xRight=(1-afrac/2-bfrac)*_this.w;var xCenter=(xLeft+xRight)/2;var xSpan=xRight-xLeft;var yBottom=(1-afrac)*_this.h;var yTop=yBottom-xSpan/whRatio;if(xSpan0.2?'rgba(0,0,0,0.4)':'rgba(255,255,255,0.3)').duration(200);corners.transition().style('opacity',1).duration(200);dimmed=true;}gd.emit('plotly_relayouting',makeUpdate(mins));}function zoomDone(){removeZoombox(gd);if(mins===mins0)return;Registry.call('_guiRelayout',gd,makeUpdate(mins));if(SHOWZOOMOUTTIP&&gd.data&&gd._context.showTips){Lib.notifier(_(gd,'Double-click to zoom back out'),'long');SHOWZOOMOUTTIP=false;}}function panPrep(){mins0={a:_this.aaxis.range[0],b:_this.baxis.range[1],c:_this.caxis.range[1]};mins=mins0;}function plotDrag(dx,dy){var dxScaled=dx/_this.xaxis._m;var dyScaled=dy/_this.yaxis._m;mins={a:mins0.a-dyScaled,b:mins0.b+(dxScaled+dyScaled)/2,c:mins0.c-(dxScaled-dyScaled)/2};var minsorted=[mins.a,mins.b,mins.c].sort();var minindices={a:minsorted.indexOf(mins.a),b:minsorted.indexOf(mins.b),c:minsorted.indexOf(mins.c)};if(minsorted[0]<0){if(minsorted[1]+minsorted[0]/2<0){minsorted[2]+=minsorted[0]+minsorted[1];minsorted[0]=minsorted[1]=0;}else{minsorted[2]+=minsorted[0]/2;minsorted[1]+=minsorted[0]/2;minsorted[0]=0;}mins={a:minsorted[minindices.a],b:minsorted[minindices.b],c:minsorted[minindices.c]};dy=(mins0.a-mins.a)*_this.yaxis._m;dx=(mins0.c-mins.c-mins0.b+mins.b)*_this.xaxis._m;}// move the data (translate, don't redraw)\nvar plotTransform='translate('+(_this.x0+dx)+','+(_this.y0+dy)+')';_this.plotContainer.selectAll('.scatterlayer,.maplayer').attr('transform',plotTransform);var plotTransform2='translate('+-dx+','+-dy+')';_this.clipDefRelative.select('path').attr('transform',plotTransform2);// move the ticks\n_this.aaxis.range=[mins.a,_this.sum-mins.b-mins.c];_this.baxis.range=[_this.sum-mins.a-mins.c,mins.b];_this.caxis.range=[_this.sum-mins.a-mins.b,mins.c];_this.drawAxes(false);if(_this._hasClipOnAxisFalse){_this.plotContainer.select('.scatterlayer').selectAll('.trace').call(Drawing.hideOutsideRangePoints,_this);}gd.emit('plotly_relayouting',makeUpdate(mins));}function dragDone(){Registry.call('_guiRelayout',gd,makeUpdate(mins));}// finally, set up hover and click\n// these event handlers must already be set before dragElement.init\n// so it can stash them and override them.\ndragger.onmousemove=function(evt){Fx.hover(gd,evt,_this.id);gd._fullLayout._lasthover=dragger;gd._fullLayout._hoversubplot=_this.id;};dragger.onmouseout=function(evt){if(gd._dragging)return;dragElement.unhover(gd,evt);};dragElement.init(this.dragOptions);};function removeZoombox(gd){d3.select(gd).selectAll('.zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners').remove();}},{\"../../components/color\":602,\"../../components/dragelement\":621,\"../../components/dragelement/helpers\":620,\"../../components/drawing\":624,\"../../components/fx\":642,\"../../components/titles\":697,\"../../lib\":735,\"../../lib/extend\":726,\"../../registry\":866,\"../cartesian/axes\":783,\"../cartesian/constants\":789,\"../cartesian/select\":802,\"../cartesian/set_convert\":803,\"../plots\":846,\"d3\":165,\"tinycolor2\":535}],866:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Loggers=_dereq_('./lib/loggers');var noop=_dereq_('./lib/noop');var pushUnique=_dereq_('./lib/push_unique');var isPlainObject=_dereq_('./lib/is_plain_object');var addStyleRule=_dereq_('./lib/dom').addStyleRule;var ExtendModule=_dereq_('./lib/extend');var basePlotAttributes=_dereq_('./plots/attributes');var baseLayoutAttributes=_dereq_('./plots/layout_attributes');var extendFlat=ExtendModule.extendFlat;var extendDeepAll=ExtendModule.extendDeepAll;exports.modules={};exports.allCategories={};exports.allTypes=[];exports.subplotsRegistry={};exports.transformsRegistry={};exports.componentsRegistry={};exports.layoutArrayContainers=[];exports.layoutArrayRegexes=[];exports.traceLayoutAttributes={};exports.localeRegistry={};exports.apiMethodRegistry={};exports.collectableSubplotTypes=null;/**\n * Top-level register routine, exported as Plotly.register\n *\n * @param {object array or array of objects} _modules :\n * module object or list of module object to register.\n *\n * A valid `moduleType: 'trace'` module has fields:\n * - name {string} : the trace type\n * - categories {array} : categories associated with this trace type,\n * tested with Register.traceIs()\n * - meta {object} : meta info (mostly for plot-schema)\n *\n * A valid `moduleType: 'locale'` module has fields:\n * - name {string} : the locale name. Should be a 2-digit language string ('en', 'de')\n * optionally with a country/region code ('en-GB', 'de-CH'). If a country\n * code is used but the base language locale has not yet been supplied,\n * we will use this locale for the base as well.\n * - dictionary {object} : the dictionary mapping input strings to localized strings\n * generally the keys should be the literal input strings, but\n * if default translations are provided you can use any string as a key.\n * - format {object} : a `d3.locale` format specifier for this locale\n * any omitted keys we'll fall back on en-US.\n *\n * A valid `moduleType: 'transform'` module has fields:\n * - name {string} : transform name\n * - transform {function} : default-level transform function\n * - calcTransform {function} : calc-level transform function\n * - attributes {object} : transform attributes declarations\n * - supplyDefaults {function} : attributes default-supply function\n *\n * A valid `moduleType: 'component'` module has fields:\n * - name {string} : the component name, used it with Register.getComponentMethod()\n * to employ component method.\n *\n * A valid `moduleType: 'apiMethod'` module has fields:\n * - name {string} : the api method name.\n * - fn {function} : the api method called with Register.call();\n *\n */exports.register=function register(_modules){exports.collectableSubplotTypes=null;if(!_modules){throw new Error('No argument passed to Plotly.register.');}else if(_modules&&!Array.isArray(_modules)){_modules=[_modules];}for(var i=0;i<_modules.length;i++){var newModule=_modules[i];if(!newModule){throw new Error('Invalid module was attempted to be registered!');}switch(newModule.moduleType){case'trace':registerTraceModule(newModule);break;case'transform':registerTransformModule(newModule);break;case'component':registerComponentModule(newModule);break;case'locale':registerLocale(newModule);break;case'apiMethod':var name=newModule.name;exports.apiMethodRegistry[name]=newModule.fn;break;default:throw new Error('Invalid module was attempted to be registered!');}}};/**\n * Get registered module using trace object or trace type\n *\n * @param {object||string} trace\n * trace object with prop 'type' or trace type as a string\n * @return {object}\n * module object corresponding to trace type\n */exports.getModule=function(trace){var _module=exports.modules[getTraceType(trace)];if(!_module)return false;return _module._module;};/**\n * Determine if this trace type is in a given category\n *\n * @param {object||string} traceType\n * a trace (object) or trace type (string)\n * @param {string} category\n * category in question\n * @return {boolean}\n */exports.traceIs=function(traceType,category){traceType=getTraceType(traceType);// old Chart Studio Cloud workspace hack, nothing to see here\nif(traceType==='various')return false;var _module=exports.modules[traceType];if(!_module){if(traceType&&traceType!=='area'){Loggers.log('Unrecognized trace type '+traceType+'.');}_module=exports.modules[basePlotAttributes.type.dflt];}return!!_module.categories[category];};/**\n * Determine if this trace has a transform of the given type and return\n * array of matching indices.\n *\n * @param {object} data\n * a trace object (member of data or fullData)\n * @param {string} type\n * type of trace to test\n * @return {array}\n * array of matching indices. If none found, returns []\n */exports.getTransformIndices=function(data,type){var indices=[];var transforms=data.transforms||[];for(var i=0;i-1;}module.exports=function clonePlot(graphObj,options){// Polar plot compatibility\nif(graphObj.framework&&graphObj.framework.isPolar){graphObj=graphObj.framework.getConfig();}var i;var oldData=graphObj.data;var oldLayout=graphObj.layout;var newData=extendDeep([],oldData);var newLayout=extendDeep({},oldLayout,cloneLayoutOverride(options.tileClass));var context=graphObj._context||{};if(options.width)newLayout.width=options.width;if(options.height)newLayout.height=options.height;if(options.tileClass==='thumbnail'||options.tileClass==='themes__thumb'){// kill annotations\nnewLayout.annotations=[];var keys=Object.keys(newLayout);for(i=0;i\n * or an id to an existing graph \n * @param {object} opts (see Plotly.toImage in ../plot_api/to_image)\n * @return {promise}\n */function downloadImage(gd,opts){var _gd;if(!Lib.isPlainObject(gd))_gd=Lib.getGraphDiv(gd);opts=opts||{};opts.format=opts.format||'png';opts.imageDataOnly=true;return new Promise(function(resolve,reject){if(_gd&&_gd._snapshotInProgress){reject(new Error('Snapshotting already in progress.'));}// see comments within svgtoimg for additional\n// discussion of problems with IE\n// can now draw to canvas, but CORS tainted canvas\n// does not allow toDataURL\n// svg format will work though\nif(Lib.isIE()&&opts.format!=='svg'){reject(new Error(helpers.MSG_IE_BAD_FORMAT));}if(_gd)_gd._snapshotInProgress=true;var promise=toImage(gd,opts);var filename=opts.filename||gd.fn||'newplot';filename+='.'+opts.format.replace('-','.');promise.then(function(result){if(_gd)_gd._snapshotInProgress=false;return fileSaver(result,filename,opts.format);}).then(function(name){resolve(name);}).catch(function(err){if(_gd)_gd._snapshotInProgress=false;reject(err);});});}module.exports=downloadImage;},{\"../lib\":735,\"../plot_api/to_image\":776,\"./filesaver\":869,\"./helpers\":870}],869:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Lib=_dereq_('../lib');var helpers=_dereq_('./helpers');/*\n* substantial portions of this code from FileSaver.js\n* https://github.com/eligrey/FileSaver.js\n* License: https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md\n* FileSaver.js\n* A saveAs() FileSaver implementation.\n* 1.1.20160328\n*\n* By Eli Grey, http://eligrey.com\n* License: MIT\n* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md\n*/function fileSaver(url,name,format){var saveLink=document.createElement('a');var canUseSaveLink=('download'in saveLink);var promise=new Promise(function(resolve,reject){var blob;var objectUrl;if(Lib.isIE9orBelow()){reject(new Error('IE < 10 unsupported'));}// Safari doesn't allow downloading of blob urls\nif(Lib.isSafari()){var prefix=format==='svg'?',':';base64,';helpers.octetStream(prefix+encodeURIComponent(url));return resolve(name);}// IE 10+ (native saveAs)\nif(Lib.isIE()){// At this point we are only dealing with a decoded SVG as\n// a data URL (since IE only supports SVG)\nblob=helpers.createBlob(url,'svg');window.navigator.msSaveBlob(blob,name);blob=null;return resolve(name);}if(canUseSaveLink){blob=helpers.createBlob(url,format);objectUrl=helpers.createObjectURL(blob);saveLink.href=objectUrl;saveLink.download=name;document.body.appendChild(saveLink);saveLink.click();document.body.removeChild(saveLink);helpers.revokeObjectURL(objectUrl);blob=null;return resolve(name);}reject(new Error('download error'));});return promise;}module.exports=fileSaver;},{\"../lib\":735,\"./helpers\":870}],870:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Registry=_dereq_('../registry');exports.getDelay=function(fullLayout){if(!fullLayout._has)return 0;return fullLayout._has('gl3d')||fullLayout._has('gl2d')||fullLayout._has('mapbox')?500:0;};exports.getRedrawFunc=function(gd){return function(){var fullLayout=gd._fullLayout||{};var hasPolar=fullLayout._has&&fullLayout._has('polar');var hasLegacyPolar=!hasPolar&&gd.data&&gd.data[0]&&gd.data[0].r;if(!hasLegacyPolar){Registry.getComponentMethod('colorbar','draw')(gd);}};};exports.encodeSVG=function(svg){return'data:image/svg+xml,'+encodeURIComponent(svg);};exports.encodeJSON=function(json){return'data:application/json,'+encodeURIComponent(json);};var DOM_URL=window.URL||window.webkitURL;exports.createObjectURL=function(blob){return DOM_URL.createObjectURL(blob);};exports.revokeObjectURL=function(url){return DOM_URL.revokeObjectURL(url);};exports.createBlob=function(url,format){if(format==='svg'){return new window.Blob([url],{type:'image/svg+xml;charset=utf-8'});}else if(format==='full-json'){return new window.Blob([url],{type:'application/json;charset=utf-8'});}else{var binary=fixBinary(window.atob(url));return new window.Blob([binary],{type:'image/'+format});}};exports.octetStream=function(s){document.location.href='data:application/octet-stream'+s;};// Taken from https://bl.ocks.org/nolanlawson/0eac306e4dac2114c752\nfunction fixBinary(b){var len=b.length;var buf=new ArrayBuffer(len);var arr=new Uint8Array(buf);for(var i=0;i
')!==-1){return'';}return hiddenDiv.html(d).text();// everything else, let the browser decode it to unicode\n});hiddenDiv.remove();return replaced;}function xmlEntityEncode(str){return str.replace(/&(?!\\w+;|\\#[0-9]+;| \\#x[0-9A-F]+;)/g,'&');}module.exports=function toSVG(gd,format,scale){var fullLayout=gd._fullLayout;var svg=fullLayout._paper;var toppaper=fullLayout._toppaper;var width=fullLayout.width;var height=fullLayout.height;var i;// make background color a rect in the svg, then revert after scraping\n// all other alterations have been dealt with by properly preparing the svg\n// in the first place... like setting cursors with css classes so we don't\n// have to remove them, and providing the right namespaces in the svg to\n// begin with\nsvg.insert('rect',':first-child').call(Drawing.setRect,0,0,width,height).call(Color.fill,fullLayout.paper_bgcolor);// subplot-specific to-SVG methods\n// which notably add the contents of the gl-container\n// into the main svg node\nvar basePlotModules=fullLayout._basePlotModules||[];for(i=0;isMax+sTiny||!isNumeric(sMin));}for(var i=0;imax;if(!isOutOfBounds)return value;}return defaultValue!==undefined?defaultValue:attributeDefinition.dflt;};exports.coerceColor=function(attributeDefinition,value,defaultValue){if(tinycolor(value).isValid())return value;return defaultValue!==undefined?defaultValue:attributeDefinition.dflt;};exports.coerceEnumerated=function(attributeDefinition,value,defaultValue){if(attributeDefinition.coerceNumber)value=+value;if(attributeDefinition.values.indexOf(value)!==-1)return value;return defaultValue!==undefined?defaultValue:attributeDefinition.dflt;};exports.getValue=function(arrayOrScalar,index){var value;if(!Array.isArray(arrayOrScalar))value=arrayOrScalar;else if(index0){s+=rawS;}else if(v<0){s-=rawS;}}// add a gradient so hovering near the end of a\n// bar makes it a little closer match\nreturn Fx.inbox(b-v,s-v,maxHoverDistance+(s-v)/(s-b)-1);}if(trace.orientation==='h'){posVal=yval;sizeVal=xval;posLetter='y';sizeLetter='x';dx=sizeFn;dy=positionFn;}else{posVal=xval;sizeVal=yval;posLetter='x';sizeLetter='y';dy=sizeFn;dx=positionFn;}var pa=pointData[posLetter+'a'];var sa=pointData[sizeLetter+'a'];pRangeCalc=Math.abs(pa.r2c(pa.range[1])-pa.r2c(pa.range[0]));function dxy(di){return(dx(di)+dy(di))/2;}var distfn=Fx.getDistanceFunction(hovermode,dx,dy,dxy);Fx.getClosest(cd,distfn,pointData);// skip the rest (for this trace) if we didn't find a close point\nif(pointData.index===false)return;// skip points inside axis rangebreaks\nif(cd[pointData.index].p===BADNUM)return;// if we get here and we're not in 'closest' mode, push min/max pos back\n// onto the group - even though that means occasionally the mouse will be\n// over the hover label.\nif(!isClosest){minPos=function(di){return Math.min(thisBarMinPos(di),di.p-t.bargroupwidth/2);};maxPos=function(di){return Math.max(thisBarMaxPos(di),di.p+t.bargroupwidth/2);};}// the closest data point\nvar index=pointData.index;var di=cd[index];var size=trace.base?di.b+di.s:di.s;pointData[sizeLetter+'0']=pointData[sizeLetter+'1']=sa.c2p(di[sizeLetter],true);pointData[sizeLetter+'LabelVal']=size;var extent=t.extents[t.extents.round(di.p)];pointData[posLetter+'0']=pa.c2p(isClosest?minPos(di):extent[0],true);pointData[posLetter+'1']=pa.c2p(isClosest?maxPos(di):extent[1],true);pointData[posLetter+'LabelVal']=di.p;pointData.labelLabel=hoverLabelText(pa,pointData[posLetter+'LabelVal']);pointData.valueLabel=hoverLabelText(sa,pointData[sizeLetter+'LabelVal']);// spikelines always want \"closest\" distance regardless of hovermode\npointData.spikeDistance=(sizeFn(di)+thisBarPositionFn(di))/2-maxHoverDistance;// they also want to point to the data value, regardless of where the label goes\n// in case of bars shifted within groups\npointData[posLetter+'Spike']=pa.c2p(di.p,true);fillText(di,trace,pointData);pointData.hovertemplate=trace.hovertemplate;return pointData;}function getTraceColor(trace,di){var mc=di.mcc||trace.marker.color;var mlc=di.mlcc||trace.marker.line.color;var mlw=getLineWidth(trace,di);if(Color.opacity(mc))return mc;else if(Color.opacity(mlc)&&mlw)return mlc;}module.exports={hoverPoints:hoverPoints,hoverOnBars:hoverOnBars,getTraceColor:getTraceColor};},{\"../../components/color\":602,\"../../components/fx\":642,\"../../constants/numerical\":711,\"../../lib\":735,\"../../plots/cartesian/axes\":783,\"../../registry\":866,\"./helpers\":882}],884:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';module.exports={attributes:_dereq_('./attributes'),layoutAttributes:_dereq_('./layout_attributes'),supplyDefaults:_dereq_('./defaults').supplyDefaults,crossTraceDefaults:_dereq_('./defaults').crossTraceDefaults,supplyLayoutDefaults:_dereq_('./layout_defaults'),calc:_dereq_('./calc'),crossTraceCalc:_dereq_('./cross_trace_calc').crossTraceCalc,colorbar:_dereq_('../scatter/marker_colorbar'),arraysToCalcdata:_dereq_('./arrays_to_calcdata'),plot:_dereq_('./plot').plot,style:_dereq_('./style').style,styleOnSelect:_dereq_('./style').styleOnSelect,hoverPoints:_dereq_('./hover').hoverPoints,eventData:_dereq_('./event_data'),selectPoints:_dereq_('./select'),moduleType:'trace',name:'bar',basePlotModule:_dereq_('../../plots/cartesian'),categories:['bar-like','cartesian','svg','bar','oriented','errorBarsOK','showLegend','zoomScale'],animatable:true,meta:{}};},{\"../../plots/cartesian\":796,\"../scatter/marker_colorbar\":1158,\"./arrays_to_calcdata\":875,\"./attributes\":876,\"./calc\":877,\"./cross_trace_calc\":879,\"./defaults\":880,\"./event_data\":881,\"./hover\":883,\"./layout_attributes\":885,\"./layout_defaults\":886,\"./plot\":887,\"./select\":888,\"./style\":890}],885:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';module.exports={barmode:{valType:'enumerated',values:['stack','group','overlay','relative'],dflt:'group',editType:'calc'},barnorm:{valType:'enumerated',values:['','fraction','percent'],dflt:'',editType:'calc'},bargap:{valType:'number',min:0,max:1,editType:'calc'},bargroupgap:{valType:'number',min:0,max:1,dflt:0,editType:'calc'}};},{}],886:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Registry=_dereq_('../../registry');var Axes=_dereq_('../../plots/cartesian/axes');var Lib=_dereq_('../../lib');var layoutAttributes=_dereq_('./layout_attributes');module.exports=function(layoutIn,layoutOut,fullData){function coerce(attr,dflt){return Lib.coerce(layoutIn,layoutOut,layoutAttributes,attr,dflt);}var hasBars=false;var shouldBeGapless=false;var gappedAnyway=false;var usedSubplots={};var mode=coerce('barmode');for(var i=0;i0;}function plot(gd,plotinfo,cdModule,traceLayer,opts,makeOnCompleteCallback){var xa=plotinfo.xaxis;var ya=plotinfo.yaxis;var fullLayout=gd._fullLayout;if(!opts){opts={mode:fullLayout.barmode,norm:fullLayout.barmode,gap:fullLayout.bargap,groupgap:fullLayout.bargroupgap};// don't clear bar when this is called from waterfall or funnel\nclearMinTextSize('bar',fullLayout);}var bartraces=Lib.makeTraceGroups(traceLayer,cdModule,'trace bars').each(function(cd){var plotGroup=d3.select(this);var trace=cd[0].trace;var isWaterfall=trace.type==='waterfall';var isFunnel=trace.type==='funnel';var isBar=trace.type==='bar';var shouldDisplayZeros=isBar||isFunnel;var adjustPixel=0;if(isWaterfall&&trace.connector.visible&&trace.connector.mode==='between'){adjustPixel=trace.connector.line.width/2;}var isHorizontal=trace.orientation==='h';var withTransition=hasTransition(opts);var pointGroup=Lib.ensureSingle(plotGroup,'g','points');var keyFunc=getKeyFunc(trace);var bars=pointGroup.selectAll('g.point').data(Lib.identity,keyFunc);bars.enter().append('g').classed('point',true);bars.exit().remove();bars.each(function(di,i){var bar=d3.select(this);// now display the bar\n// clipped xf/yf (2nd arg true): non-positive\n// log values go off-screen by plotwidth\n// so you see them continue if you drag the plot\nvar xy=getXY(di,xa,ya,isHorizontal);var x0=xy[0][0];var x1=xy[0][1];var y0=xy[1][0];var y1=xy[1][1];// empty bars\nvar isBlank=(isHorizontal?x1-x0:y1-y0)===0;// display zeros if line.width > 0\nif(isBlank&&shouldDisplayZeros&&helpers.getLineWidth(trace,di)){isBlank=false;}// skip nulls\nif(!isBlank){isBlank=!isNumeric(x0)||!isNumeric(x1)||!isNumeric(y0)||!isNumeric(y1);}// record isBlank\ndi.isBlank=isBlank;// for blank bars, ensure start and end positions are equal - important for smooth transitions\nif(isBlank){if(isHorizontal){x1=x0;}else{y1=y0;}}// in waterfall mode `between` we need to adjust bar end points to match the connector width\nif(adjustPixel&&!isBlank){if(isHorizontal){x0-=dirSign(x0,x1)*adjustPixel;x1+=dirSign(x0,x1)*adjustPixel;}else{y0-=dirSign(y0,y1)*adjustPixel;y1+=dirSign(y0,y1)*adjustPixel;}}var lw;var mc;if(trace.type==='waterfall'){if(!isBlank){var cont=trace[di.dir].marker;lw=cont.line.width;mc=cont.color;}}else{lw=helpers.getLineWidth(trace,di);mc=di.mc||trace.marker.color;}function roundWithLine(v){var offset=d3.round(lw/2%1,2);// if there are explicit gaps, don't round,\n// it can make the gaps look crappy\nreturn opts.gap===0&&opts.groupgap===0?d3.round(Math.round(v)-offset,2):v;}function expandToVisible(v,vc,hideZeroSpan){if(hideZeroSpan&&v===vc){// should not expand zero span bars\n// when start and end positions are identical\n// i.e. for vertical when y0 === y1\n// and for horizontal when x0 === x1\nreturn v;}// if it's not in danger of disappearing entirely,\n// round more precisely\nreturn Math.abs(v-vc)>=2?roundWithLine(v):// but if it's very thin, expand it so it's\n// necessarily visible, even if it might overlap\n// its neighbor\nv>vc?Math.ceil(v):Math.floor(v);}if(!gd._context.staticPlot){// if bars are not fully opaque or they have a line\n// around them, round to integer pixels, mainly for\n// safari so we prevent overlaps from its expansive\n// pixelation. if the bars ARE fully opaque and have\n// no line, expand to a full pixel to make sure we\n// can see them\nvar op=Color.opacity(mc);var fixpx=op<1||lw>0.01?roundWithLine:expandToVisible;x0=fixpx(x0,x1,isHorizontal);x1=fixpx(x1,x0,isHorizontal);y0=fixpx(y0,y1,!isHorizontal);y1=fixpx(y1,y0,!isHorizontal);}var sel=transition(Lib.ensureSingle(bar,'path'),fullLayout,opts,makeOnCompleteCallback);sel.style('vector-effect','non-scaling-stroke').attr('d',isNaN((x1-x0)*(y1-y0))?'M0,0Z':'M'+x0+','+y0+'V'+y1+'H'+x1+'V'+y0+'Z').call(Drawing.setClipUrl,plotinfo.layerClipId,gd);if(!fullLayout.uniformtext.mode&&withTransition){var styleFns=Drawing.makePointStyleFns(trace);Drawing.singlePointStyle(di,sel,trace,styleFns,gd);}appendBarText(gd,plotinfo,bar,cd,i,x0,x1,y0,y1,opts,makeOnCompleteCallback);if(plotinfo.layerClipId){Drawing.hideOutsideRangePoint(di,bar.select('text'),xa,ya,trace.xcalendar,trace.ycalendar);}});// lastly, clip points groups of `cliponaxis !== false` traces\n// on `plotinfo._hasClipOnAxisFalse === true` subplots\nvar hasClipOnAxisFalse=trace.cliponaxis===false;Drawing.setClipUrl(plotGroup,hasClipOnAxisFalse?null:plotinfo.layerClipId,gd);});// error bars are on the top\nRegistry.getComponentMethod('errorbars','plot')(gd,bartraces,plotinfo,opts);}function appendBarText(gd,plotinfo,bar,cd,i,x0,x1,y0,y1,opts,makeOnCompleteCallback){var xa=plotinfo.xaxis;var ya=plotinfo.yaxis;var fullLayout=gd._fullLayout;var textPosition;function appendTextNode(bar,text,font){var textSelection=Lib.ensureSingle(bar,'text').text(text).attr({'class':'bartext bartext-'+textPosition,'text-anchor':'middle',// prohibit tex interpretation until we can handle\n// tex and regular text together\n'data-notex':1}).call(Drawing.font,font).call(svgTextUtils.convertToTspans,gd);return textSelection;}// get trace attributes\nvar trace=cd[0].trace;var isHorizontal=trace.orientation==='h';var text=getText(fullLayout,cd,i,xa,ya);textPosition=getTextPosition(trace,i);// compute text position\nvar inStackOrRelativeMode=opts.mode==='stack'||opts.mode==='relative';var calcBar=cd[i];var isOutmostBar=!inStackOrRelativeMode||calcBar._outmost;if(!text||textPosition==='none'||(calcBar.isBlank||x0===x1||y0===y1)&&(textPosition==='auto'||textPosition==='inside')){bar.select('text').remove();return;}var layoutFont=fullLayout.font;var barColor=style.getBarColor(cd[i],trace);var insideTextFont=style.getInsideTextFont(trace,i,layoutFont,barColor);var outsideTextFont=style.getOutsideTextFont(trace,i,layoutFont);// Special case: don't use the c2p(v, true) value on log size axes,\n// so that we can get correctly inside text scaling\nvar di=bar.datum();if(isHorizontal){if(xa.type==='log'&&di.s0<=0){if(xa.range[0]0&&textHeight>0;var fitsInside=textWidth<=barWidth&&textHeight<=barHeight;var fitsInsideIfRotated=textWidth<=barHeight&&textHeight<=barWidth;var fitsInsideIfShrunk=isHorizontal?barWidth>=textWidth*(barHeight/textHeight):barHeight>=textHeight*(barWidth/textWidth);if(textHasSize&&(fitsInside||fitsInsideIfRotated||fitsInsideIfShrunk)){textPosition='inside';}else{textPosition='outside';textSelection.remove();textSelection=null;}}else{textPosition='inside';}}if(!textSelection){font=Lib.ensureUniformFontSize(gd,textPosition==='outside'?outsideTextFont:insideTextFont);textSelection=appendTextNode(bar,text,font);var currentTransform=textSelection.attr('transform');textSelection.attr('transform','');textBB=Drawing.bBox(textSelection.node()),textWidth=textBB.width,textHeight=textBB.height;textSelection.attr('transform',currentTransform);if(textWidth<=0||textHeight<=0){textSelection.remove();return;}}var angle=trace.textangle;// compute text transform\nvar transform,constrained;if(textPosition==='outside'){constrained=trace.constraintext==='both'||trace.constraintext==='outside';transform=toMoveOutsideBar(x0,x1,y0,y1,textBB,{isHorizontal:isHorizontal,constrained:constrained,angle:angle});}else{constrained=trace.constraintext==='both'||trace.constraintext==='inside';transform=toMoveInsideBar(x0,x1,y0,y1,textBB,{isHorizontal:isHorizontal,constrained:constrained,angle:angle,anchor:trace.insidetextanchor});}transform.fontSize=font.size;recordMinTextSize(trace.type,transform,fullLayout);calcBar.transform=transform;transition(textSelection,fullLayout,opts,makeOnCompleteCallback).attr('transform',Lib.getTextTransform(transform));}function getRotateFromAngle(angle){return angle==='auto'?0:angle;}function getRotatedTextSize(textBB,rotate){var a=Math.PI/180*rotate;var absSin=Math.abs(Math.sin(a));var absCos=Math.abs(Math.cos(a));return{x:textBB.width*absCos+textBB.height*absSin,y:textBB.width*absSin+textBB.height*absCos};}function toMoveInsideBar(x0,x1,y0,y1,textBB,opts){var isHorizontal=!!opts.isHorizontal;var constrained=!!opts.constrained;var angle=opts.angle||0;var anchor=opts.anchor||'end';var isEnd=anchor==='end';var isStart=anchor==='start';var leftToRight=opts.leftToRight||0;// left: -1, center: 0, right: 1\nvar toRight=(leftToRight+1)/2;var toLeft=1-toRight;var textWidth=textBB.width;var textHeight=textBB.height;var lx=Math.abs(x1-x0);var ly=Math.abs(y1-y0);// compute remaining space\nvar textpad=lx>2*TEXTPAD&&ly>2*TEXTPAD?TEXTPAD:0;lx-=2*textpad;ly-=2*textpad;var rotate=getRotateFromAngle(angle);if(angle==='auto'&&!(textWidth<=lx&&textHeight<=ly)&&(textWidth>lx||textHeight>ly)&&(!(textWidth>ly||textHeight>lx)||textWidth2*TEXTPAD?TEXTPAD:0;}else{textpad=lx>2*TEXTPAD?TEXTPAD:0;}// compute rotate and scale\nvar scale=1;if(constrained){scale=isHorizontal?Math.min(1,ly/textHeight):Math.min(1,lx/textWidth);}var rotate=getRotateFromAngle(angle);var t=getRotatedTextSize(textBB,rotate);// compute text and target positions\nvar extrapad=(isHorizontal?t.x:t.y)/2;var textX=(textBB.left+textBB.right)/2;var textY=(textBB.top+textBB.bottom)/2;var targetX=(x0+x1)/2;var targetY=(y0+y1)/2;var anchorX=0;var anchorY=0;var dir=isHorizontal?dirSign(x1,x0):dirSign(y0,y1);if(isHorizontal){targetX=x1-dir*textpad;anchorX=dir*extrapad;}else{targetY=y1+dir*textpad;anchorY=-dir*extrapad;}return{textX:textX,textY:textY,targetX:targetX,targetY:targetY,anchorX:anchorX,anchorY:anchorY,scale:scale,rotate:rotate};}function getText(fullLayout,cd,index,xa,ya){var trace=cd[0].trace;var texttemplate=trace.texttemplate;var value;if(texttemplate){value=calcTexttemplate(fullLayout,cd,index,xa,ya);}else if(trace.textinfo){value=calcTextinfo(cd,index,xa,ya);}else{value=helpers.getValue(trace.text,index);}return helpers.coerceString(attributeText,value);}function getTextPosition(trace,index){var value=helpers.getValue(trace.textposition,index);return helpers.coerceEnumerated(attributeTextPosition,value);}function calcTexttemplate(fullLayout,cd,index,xa,ya){var trace=cd[0].trace;var texttemplate=Lib.castOption(trace,index,'texttemplate');if(!texttemplate)return'';var isWaterfall=trace.type==='waterfall';var isFunnel=trace.type==='funnel';var pLetter,pAxis;var vLetter,vAxis;if(trace.orientation==='h'){pLetter='y';pAxis=ya;vLetter='x';vAxis=xa;}else{pLetter='x';pAxis=xa;vLetter='y';vAxis=ya;}function formatLabel(u){return tickText(pAxis,u,true).text;}function formatNumber(v){return tickText(vAxis,+v,true).text;}var cdi=cd[index];var obj={};obj.label=cdi.p;obj.labelLabel=obj[pLetter+'Label']=formatLabel(cdi.p);var tx=Lib.castOption(trace,cdi.i,'text');if(tx===0||tx)obj.text=tx;obj.value=cdi.s;obj.valueLabel=obj[vLetter+'Label']=formatNumber(cdi.s);var pt={};appendArrayPointValue(pt,trace,cdi.i);if(isWaterfall){obj.delta=+cdi.rawS||cdi.s;obj.deltaLabel=formatNumber(obj.delta);obj.final=cdi.v;obj.finalLabel=formatNumber(obj.final);obj.initial=obj.final-obj.delta;obj.initialLabel=formatNumber(obj.initial);}if(isFunnel){obj.value=cdi.s;obj.valueLabel=formatNumber(obj.value);obj.percentInitial=cdi.begR;obj.percentInitialLabel=Lib.formatPercent(cdi.begR);obj.percentPrevious=cdi.difR;obj.percentPreviousLabel=Lib.formatPercent(cdi.difR);obj.percentTotal=cdi.sumR;obj.percenTotalLabel=Lib.formatPercent(cdi.sumR);}var customdata=Lib.castOption(trace,cdi.i,'customdata');if(customdata)obj.customdata=customdata;return Lib.texttemplateString(texttemplate,obj,fullLayout._d3locale,pt,obj,trace._meta||{});}function calcTextinfo(cd,index,xa,ya){var trace=cd[0].trace;var isHorizontal=trace.orientation==='h';var isWaterfall=trace.type==='waterfall';var isFunnel=trace.type==='funnel';function formatLabel(u){var pAxis=isHorizontal?ya:xa;return tickText(pAxis,u,true).text;}function formatNumber(v){var sAxis=isHorizontal?xa:ya;return tickText(sAxis,+v,true).text;}var textinfo=trace.textinfo;var cdi=cd[index];var parts=textinfo.split('+');var text=[];var tx;var hasFlag=function(flag){return parts.indexOf(flag)!==-1;};if(hasFlag('label')){text.push(formatLabel(cd[index].p));}if(hasFlag('text')){tx=Lib.castOption(trace,cdi.i,'text');if(tx===0||tx)text.push(tx);}if(isWaterfall){var delta=+cdi.rawS||cdi.s;var final=cdi.v;var initial=final-delta;if(hasFlag('initial'))text.push(formatNumber(initial));if(hasFlag('delta'))text.push(formatNumber(delta));if(hasFlag('final'))text.push(formatNumber(final));}if(isFunnel){if(hasFlag('value'))text.push(formatNumber(cdi.s));var nPercent=0;if(hasFlag('percent initial'))nPercent++;if(hasFlag('percent previous'))nPercent++;if(hasFlag('percent total'))nPercent++;var hasMultiplePercents=nPercent>1;if(hasFlag('percent initial')){tx=Lib.formatPercent(cdi.begR);if(hasMultiplePercents)tx+=' of initial';text.push(tx);}if(hasFlag('percent previous')){tx=Lib.formatPercent(cdi.difR);if(hasMultiplePercents)tx+=' of previous';text.push(tx);}if(hasFlag('percent total')){tx=Lib.formatPercent(cdi.sumR);if(hasMultiplePercents)tx+=' of total';text.push(tx);}}return text.join(' ');}module.exports={plot:plot,toMoveInsideBar:toMoveInsideBar};},{\"../../components/color\":602,\"../../components/drawing\":624,\"../../components/fx/helpers\":638,\"../../lib\":735,\"../../lib/svg_text_utils\":759,\"../../plots/cartesian/axes\":783,\"../../registry\":866,\"./attributes\":876,\"./constants\":878,\"./helpers\":882,\"./style\":890,\"./uniform_text\":892,\"d3\":165,\"fast-isnumeric\":237}],888:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';module.exports=function selectPoints(searchInfo,selectionTester){var cd=searchInfo.cd;var xa=searchInfo.xaxis;var ya=searchInfo.yaxis;var trace=cd[0].trace;var isFunnel=trace.type==='funnel';var isHorizontal=trace.orientation==='h';var selection=[];var i;if(selectionTester===false){// clear selection\nfor(i=0;i1||fullLayout.bargap===0&&fullLayout.bargroupgap===0&&!d[0].trace.marker.line.width){d3.select(this).attr('shape-rendering','crispEdges');}});s.selectAll('g.points').each(function(d){var sel=d3.select(this);var trace=d[0].trace;stylePoints(sel,trace,gd);});Registry.getComponentMethod('errorbars','style')(s);}function stylePoints(sel,trace,gd){Drawing.pointStyle(sel.selectAll('path'),trace,gd);styleTextPoints(sel,trace,gd);}function styleTextPoints(sel,trace,gd){sel.selectAll('text').each(function(d){var tx=d3.select(this);var font=Lib.ensureUniformFontSize(gd,determineFont(tx,d,trace,gd));Drawing.font(tx,font);});}function styleOnSelect(gd,cd,sel){var trace=cd[0].trace;if(trace.selectedpoints){stylePointsInSelectionMode(sel,trace,gd);}else{stylePoints(sel,trace,gd);Registry.getComponentMethod('errorbars','style')(sel);}}function stylePointsInSelectionMode(s,trace,gd){Drawing.selectedPointStyle(s.selectAll('path'),trace);styleTextInSelectionMode(s.selectAll('text'),trace,gd);}function styleTextInSelectionMode(txs,trace,gd){txs.each(function(d){var tx=d3.select(this);var font;if(d.selected){font=Lib.ensureUniformFontSize(gd,determineFont(tx,d,trace,gd));var selectedFontColor=trace.selected.textfont&&trace.selected.textfont.color;if(selectedFontColor){font.color=selectedFontColor;}Drawing.font(tx,font);}else{Drawing.selectedTextStyle(tx,trace);}});}function determineFont(tx,d,trace,gd){var layoutFont=gd._fullLayout.font;var textFont=trace.textfont;if(tx.classed('bartext-inside')){var barColor=getBarColor(d,trace);textFont=getInsideTextFont(trace,d.i,layoutFont,barColor);}else if(tx.classed('bartext-outside')){textFont=getOutsideTextFont(trace,d.i,layoutFont);}return textFont;}function getTextFont(trace,index,defaultValue){return getFontValue(attributeTextFont,trace.textfont,index,defaultValue);}function getInsideTextFont(trace,index,layoutFont,barColor){var defaultFont=getTextFont(trace,index,layoutFont);var wouldFallBackToLayoutFont=trace._input.textfont===undefined||trace._input.textfont.color===undefined||Array.isArray(trace.textfont.color)&&trace.textfont.color[index]===undefined;if(wouldFallBackToLayoutFont){defaultFont={color:Color.contrast(barColor),family:defaultFont.family,size:defaultFont.size};}return getFontValue(attributeInsideTextFont,trace.insidetextfont,index,defaultFont);}function getOutsideTextFont(trace,index,layoutFont){var defaultFont=getTextFont(trace,index,layoutFont);return getFontValue(attributeOutsideTextFont,trace.outsidetextfont,index,defaultFont);}function getFontValue(attributeDefinition,attributeValue,index,defaultValue){attributeValue=attributeValue||{};var familyValue=helpers.getValue(attributeValue.family,index);var sizeValue=helpers.getValue(attributeValue.size,index);var colorValue=helpers.getValue(attributeValue.color,index);return{family:helpers.coerceString(attributeDefinition.family,familyValue,defaultValue.family),size:helpers.coerceNumber(attributeDefinition.size,sizeValue,defaultValue.size),color:helpers.coerceColor(attributeDefinition.color,colorValue,defaultValue.color)};}function getBarColor(cd,trace){if(trace.type==='waterfall'){return trace[cd.dir].marker.color;}return cd.mc||trace.marker.color;}module.exports={style:style,styleTextPoints:styleTextPoints,styleOnSelect:styleOnSelect,getInsideTextFont:getInsideTextFont,getOutsideTextFont:getOutsideTextFont,getBarColor:getBarColor,resizeText:resizeText};},{\"../../components/color\":602,\"../../components/drawing\":624,\"../../lib\":735,\"../../registry\":866,\"./attributes\":876,\"./helpers\":882,\"./uniform_text\":892,\"d3\":165}],891:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Color=_dereq_('../../components/color');var hasColorscale=_dereq_('../../components/colorscale/helpers').hasColorscale;var colorscaleDefaults=_dereq_('../../components/colorscale/defaults');module.exports=function handleStyleDefaults(traceIn,traceOut,coerce,defaultColor,layout){coerce('marker.color',defaultColor);if(hasColorscale(traceIn,'marker')){colorscaleDefaults(traceIn,traceOut,layout,coerce,{prefix:'marker.',cLetter:'c'});}coerce('marker.line.color',Color.defaultLine);if(hasColorscale(traceIn,'marker.line')){colorscaleDefaults(traceIn,traceOut,layout,coerce,{prefix:'marker.line.',cLetter:'c'});}coerce('marker.line.width');coerce('marker.opacity');coerce('selected.marker.color');coerce('unselected.marker.color');};},{\"../../components/color\":602,\"../../components/colorscale/defaults\":612,\"../../components/colorscale/helpers\":613}],892:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var d3=_dereq_('d3');var Lib=_dereq_('../../lib');function resizeText(gd,gTrace,traceType){var fullLayout=gd._fullLayout;var minSize=fullLayout['_'+traceType+'Text_minsize'];if(minSize){var shouldHide=fullLayout.uniformtext.mode==='hide';var selector;switch(traceType){case'funnelarea':case'pie':case'sunburst':selector='g.slice';break;case'treemap':selector='g.slice, g.pathbar';break;default:selector='g.points > g.point';}gTrace.selectAll(selector).each(function(d){var transform=d.transform;if(transform){transform.scale=shouldHide&&transform.hide?0:minSize/transform.fontSize;var el=d3.select(this).select('text');el.attr('transform',Lib.getTextTransform(transform));}});}}function recordMinTextSize(traceType,// in\ntransform,// inout\nfullLayout// inout\n){if(fullLayout.uniformtext.mode){var minKey=getMinKey(traceType);var minSize=fullLayout.uniformtext.minsize;var size=transform.scale*transform.fontSize;transform.hide=sizeradialAxis.range[1]){thetaVal+=Math.PI;}var distFn=function(di){if(inboxFn(rVal,thetaVal,[di.rp0,di.rp1],[di.thetag0,di.thetag1],vangles)){return maxHoverDistance+// add a little to the pseudo-distance for wider bars, so that like scatter,\n// if you are over two overlapping bars, the narrower one wins.\nMath.min(1,Math.abs(di.thetag1-di.thetag0)/period)-1+// add a gradient so hovering near the end of a\n// bar makes it a little closer match\n(di.rp1-rVal)/(di.rp1-di.rp0)-1;}else{return Infinity;}};Fx.getClosest(cd,distFn,pointData);if(pointData.index===false)return;var index=pointData.index;var cdi=cd[index];pointData.x0=pointData.x1=cdi.ct[0];pointData.y0=pointData.y1=cdi.ct[1];var _cdi=Lib.extendFlat({},cdi,{r:cdi.s,theta:cdi.p});fillText(cdi,trace,pointData);makeHoverPointText(_cdi,trace,subplot,pointData);pointData.hovertemplate=trace.hovertemplate;pointData.color=getTraceColor(trace,cdi);pointData.xLabelVal=pointData.yLabelVal=undefined;if(cdi.s<0){pointData.idealAlign='left';}return[pointData];};},{\"../../components/fx\":642,\"../../lib\":735,\"../../plots/polar/helpers\":848,\"../bar/hover\":883,\"../scatterpolar/hover\":1217}],897:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';module.exports={moduleType:'trace',name:'barpolar',basePlotModule:_dereq_('../../plots/polar'),categories:['polar','bar','showLegend'],attributes:_dereq_('./attributes'),layoutAttributes:_dereq_('./layout_attributes'),supplyDefaults:_dereq_('./defaults'),supplyLayoutDefaults:_dereq_('./layout_defaults'),calc:_dereq_('./calc').calc,crossTraceCalc:_dereq_('./calc').crossTraceCalc,plot:_dereq_('./plot'),colorbar:_dereq_('../scatter/marker_colorbar'),formatLabels:_dereq_('../scatterpolar/format_labels'),style:_dereq_('../bar/style').style,styleOnSelect:_dereq_('../bar/style').styleOnSelect,hoverPoints:_dereq_('./hover'),selectPoints:_dereq_('../bar/select'),meta:{}};},{\"../../plots/polar\":849,\"../bar/select\":888,\"../bar/style\":890,\"../scatter/marker_colorbar\":1158,\"../scatterpolar/format_labels\":1216,\"./attributes\":893,\"./calc\":894,\"./defaults\":895,\"./hover\":896,\"./layout_attributes\":898,\"./layout_defaults\":899,\"./plot\":900}],898:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';module.exports={barmode:{valType:'enumerated',values:['stack','overlay'],dflt:'stack',editType:'calc'},bargap:{valType:'number',dflt:0.1,min:0,max:1,editType:'calc'}};},{}],899:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Lib=_dereq_('../../lib');var attrs=_dereq_('./layout_attributes');module.exports=function(layoutIn,layoutOut,fullData){var subplotsDone={};var sp;function coerce(attr,dflt){return Lib.coerce(layoutIn[sp]||{},layoutOut[sp],attrs,attr,dflt);}for(var i=0;i0){a0=_a0;a1=_a1;}else{a0=_a1;a1=_a0;}var va0=helpers.findEnclosingVertexAngles(a0,subplot.vangles)[0];var va1=helpers.findEnclosingVertexAngles(a1,subplot.vangles)[1];var vaBar=[va0,(a0+a1)/2,va1];return helpers.pathPolygonAnnulus(r0,r1,a0,a1,vaBar,cxx,cyy);};}return function(r0,r1,a0,a1){return Lib.pathAnnulus(r0,r1,a0,a1,cxx,cyy);};}},{\"../../components/drawing\":624,\"../../lib\":735,\"../../plots/polar/helpers\":848,\"d3\":165,\"fast-isnumeric\":237}],901:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var scatterAttrs=_dereq_('../scatter/attributes');var barAttrs=_dereq_('../bar/attributes');var colorAttrs=_dereq_('../../components/color/attributes');var hovertemplateAttrs=_dereq_('../../plots/template_attributes').hovertemplateAttrs;var extendFlat=_dereq_('../../lib/extend').extendFlat;var scatterMarkerAttrs=scatterAttrs.marker;var scatterMarkerLineAttrs=scatterMarkerAttrs.line;module.exports={y:{valType:'data_array',editType:'calc+clearAxisTypes'},x:{valType:'data_array',editType:'calc+clearAxisTypes'},x0:{valType:'any',editType:'calc+clearAxisTypes'},y0:{valType:'any',editType:'calc+clearAxisTypes'},dx:{valType:'number',editType:'calc'},dy:{valType:'number',editType:'calc'},name:{valType:'string',editType:'calc+clearAxisTypes'},q1:{valType:'data_array',editType:'calc+clearAxisTypes'},median:{valType:'data_array',editType:'calc+clearAxisTypes'},q3:{valType:'data_array',editType:'calc+clearAxisTypes'},lowerfence:{valType:'data_array',editType:'calc'},upperfence:{valType:'data_array',editType:'calc'},notched:{valType:'boolean',editType:'calc'},notchwidth:{valType:'number',min:0,max:0.5,dflt:0.25,editType:'calc'},notchspan:{valType:'data_array',editType:'calc'},// TODO\n// maybe add\n// - loweroutlierbound / upperoutlierbound\n// - lowersuspectedoutlierbound / uppersuspectedoutlierbound\nboxpoints:{valType:'enumerated',values:['all','outliers','suspectedoutliers',false],editType:'calc'},jitter:{valType:'number',min:0,max:1,editType:'calc'},pointpos:{valType:'number',min:-2,max:2,editType:'calc'},boxmean:{valType:'enumerated',values:[true,'sd',false],editType:'calc'},mean:{valType:'data_array',editType:'calc'},sd:{valType:'data_array',editType:'calc'},orientation:{valType:'enumerated',values:['v','h'],editType:'calc+clearAxisTypes'},quartilemethod:{valType:'enumerated',values:['linear','exclusive','inclusive'],dflt:'linear',editType:'calc'},width:{valType:'number',min:0,dflt:0,editType:'calc'},marker:{outliercolor:{valType:'color',dflt:'rgba(0, 0, 0, 0)',editType:'style'},symbol:extendFlat({},scatterMarkerAttrs.symbol,{arrayOk:false,editType:'plot'}),opacity:extendFlat({},scatterMarkerAttrs.opacity,{arrayOk:false,dflt:1,editType:'style'}),size:extendFlat({},scatterMarkerAttrs.size,{arrayOk:false,editType:'calc'}),color:extendFlat({},scatterMarkerAttrs.color,{arrayOk:false,editType:'style'}),line:{color:extendFlat({},scatterMarkerLineAttrs.color,{arrayOk:false,dflt:colorAttrs.defaultLine,editType:'style'}),width:extendFlat({},scatterMarkerLineAttrs.width,{arrayOk:false,dflt:0,editType:'style'}),outliercolor:{valType:'color',editType:'style'},outlierwidth:{valType:'number',min:0,dflt:1,editType:'style'},editType:'style'},editType:'plot'},line:{color:{valType:'color',editType:'style'},width:{valType:'number',min:0,dflt:2,editType:'style'},editType:'plot'},fillcolor:scatterAttrs.fillcolor,whiskerwidth:{valType:'number',min:0,max:1,dflt:0.5,editType:'calc'},offsetgroup:barAttrs.offsetgroup,alignmentgroup:barAttrs.alignmentgroup,selected:{marker:scatterAttrs.selected.marker,editType:'style'},unselected:{marker:scatterAttrs.unselected.marker,editType:'style'},text:extendFlat({},scatterAttrs.text,{}),hovertext:extendFlat({},scatterAttrs.hovertext,{}),hovertemplate:hovertemplateAttrs({}),hoveron:{valType:'flaglist',flags:['boxes','points'],dflt:'boxes+points',editType:'style'}};},{\"../../components/color/attributes\":601,\"../../lib/extend\":726,\"../../plots/template_attributes\":861,\"../bar/attributes\":876,\"../scatter/attributes\":1140}],902:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var isNumeric=_dereq_('fast-isnumeric');var Axes=_dereq_('../../plots/cartesian/axes');var Lib=_dereq_('../../lib');var BADNUM=_dereq_('../../constants/numerical').BADNUM;var _=Lib._;module.exports=function calc(gd,trace){var fullLayout=gd._fullLayout;var xa=Axes.getFromId(gd,trace.xaxis||'x');var ya=Axes.getFromId(gd,trace.yaxis||'y');var cd=[];// N.B. violin reuses same Box.calc\nvar numKey=trace.type==='violin'?'_numViolins':'_numBoxes';var i,j;var valAxis,valLetter;var posAxis,posLetter;if(trace.orientation==='h'){valAxis=xa;valLetter='x';posAxis=ya;posLetter='y';}else{valAxis=ya;valLetter='y';posAxis=xa;posLetter='x';}var posArray=getPos(trace,posLetter,posAxis,fullLayout[numKey]);var dv=Lib.distinctVals(posArray);var posDistinct=dv.vals;var dPos=dv.minDiff/2;// item in trace calcdata\nvar cdi;// array of {v: v, i, i} sample pts\nvar pts;// values of the `pts` array of objects\nvar boxVals;// length of sample\nvar N;// single sample point\nvar pt;// single sample value\nvar v;// filter function for outlier pts\n// outlier definition based on http://www.physics.csbsju.edu/stats/box2.html\nvar ptFilterFn=(trace.boxpoints||trace.points)==='all'?Lib.identity:function(pt){return pt.vcdi.uf;};if(trace._hasPreCompStats){var valArrayRaw=trace[valLetter];var d2c=function(k){return valAxis.d2c((trace[k]||[])[i]);};var minVal=Infinity;var maxVal=-Infinity;for(i=0;i=cdi.q1&&cdi.q3>=cdi.med){var lf=d2c('lowerfence');cdi.lf=lf!==BADNUM&&lf<=cdi.q1?lf:computeLowerFence(cdi,boxVals,N);var uf=d2c('upperfence');cdi.uf=uf!==BADNUM&&uf>=cdi.q3?uf:computeUpperFence(cdi,boxVals,N);var mean=d2c('mean');cdi.mean=mean!==BADNUM?mean:N?Lib.mean(boxVals,N):(cdi.q1+cdi.q3)/2;var sd=d2c('sd');cdi.sd=mean!==BADNUM&&sd>=0?sd:N?Lib.stdev(boxVals,N,cdi.mean):cdi.q3-cdi.q1;cdi.lo=computeLowerOutlierBound(cdi);cdi.uo=computeUpperOutlierBound(cdi);var ns=d2c('notchspan');ns=ns!==BADNUM&&ns>0?ns:computeNotchSpan(cdi,N);cdi.ln=cdi.med-ns;cdi.un=cdi.med+ns;var imin=cdi.lf;var imax=cdi.uf;if(trace.boxpoints&&boxVals.length){imin=Math.min(imin,boxVals[0]);imax=Math.max(imax,boxVals[N-1]);}if(trace.notched){imin=Math.min(imin,cdi.ln);imax=Math.max(imax,cdi.un);}cdi.min=imin;cdi.max=imax;}else{Lib.warn(['Invalid input - make sure that q1 <= median <= q3','q1 = '+cdi.q1,'median = '+cdi.med,'q3 = '+cdi.q3].join('\\n'));var v0;if(cdi.med!==BADNUM){v0=cdi.med;}else if(cdi.q1!==BADNUM){if(cdi.q3!==BADNUM)v0=(cdi.q1+cdi.q3)/2;else v0=cdi.q1;}else if(cdi.q3!==BADNUM){v0=cdi.q3;}else{v0=0;}// draw box as line segment\ncdi.med=v0;cdi.q1=cdi.q3=v0;cdi.lf=cdi.uf=v0;cdi.mean=cdi.sd=v0;cdi.ln=cdi.un=v0;cdi.min=cdi.max=v0;}minVal=Math.min(minVal,cdi.min);maxVal=Math.max(maxVal,cdi.max);cdi.pts2=pts.filter(ptFilterFn);cd.push(cdi);}trace._extremes[valAxis._id]=Axes.findExtremes(valAxis,[minVal,maxVal],{padded:true});}else{var valArray=valAxis.makeCalcdata(trace,valLetter);var posBins=makeBins(posDistinct,dPos);var pLen=posDistinct.length;var ptsPerBin=initNestedArray(pLen);// bin pts info per position bins\nfor(i=0;i=0&&n0){cdi={};cdi.pos=cdi[posLetter]=posDistinct[i];pts=cdi.pts=ptsPerBin[i].sort(sortByVal);boxVals=cdi[valLetter]=pts.map(extractVal);N=boxVals.length;cdi.min=boxVals[0];cdi.max=boxVals[N-1];cdi.mean=Lib.mean(boxVals,N);cdi.sd=Lib.stdev(boxVals,N,cdi.mean);cdi.med=Lib.interp(boxVals,0.5);if(N%2&&(usesExclusive||usesInclusive)){var lower;var upper;if(usesExclusive){// do NOT include the median in either half\nlower=boxVals.slice(0,N/2);upper=boxVals.slice(N/2+1);}else if(usesInclusive){// include the median in either half\nlower=boxVals.slice(0,N/2+1);upper=boxVals.slice(N/2);}cdi.q1=Lib.interp(lower,0.5);cdi.q3=Lib.interp(upper,0.5);}else{cdi.q1=Lib.interp(boxVals,0.25);cdi.q3=Lib.interp(boxVals,0.75);}// lower and upper fences\ncdi.lf=computeLowerFence(cdi,boxVals,N);cdi.uf=computeUpperFence(cdi,boxVals,N);// lower and upper outliers bounds\ncdi.lo=computeLowerOutlierBound(cdi);cdi.uo=computeUpperOutlierBound(cdi);// lower and upper notches\nvar mci=computeNotchSpan(cdi,N);cdi.ln=cdi.med-mci;cdi.un=cdi.med+mci;minLowerNotch=Math.min(minLowerNotch,cdi.ln);maxUpperNotch=Math.max(maxUpperNotch,cdi.un);cdi.pts2=pts.filter(ptFilterFn);cd.push(cdi);}}trace._extremes[valAxis._id]=Axes.findExtremes(valAxis,trace.notched?valArray.concat([minLowerNotch,maxUpperNotch]):valArray,{padded:true});}calcSelection(cd,trace);if(cd.length>0){cd[0].t={num:fullLayout[numKey],dPos:dPos,posLetter:posLetter,valLetter:valLetter,labels:{med:_(gd,'median:'),min:_(gd,'min:'),q1:_(gd,'q1:'),q3:_(gd,'q3:'),max:_(gd,'max:'),mean:trace.boxmean==='sd'?_(gd,'mean ± σ:'):_(gd,'mean:'),lf:_(gd,'lower fence:'),uf:_(gd,'upper fence:')}};fullLayout[numKey]++;return cd;}else{return[{t:{empty:true}}];}};// In vertical (horizontal) box plots:\n// if no x (y) data, use x0 (y0), or name\n// so if you want one box\n// per trace, set x0 (y0) to the x (y) value or category for this trace\n// (or set x (y) to a constant array matching y (x))\nfunction getPos(trace,posLetter,posAxis,num){var hasPosArray=(posLetter in trace);var hasPos0=(posLetter+'0'in trace);var hasPosStep=('d'+posLetter in trace);if(hasPosArray||hasPos0&&hasPosStep){return posAxis.makeCalcdata(trace,posLetter);}var pos0;if(hasPos0){pos0=trace[posLetter+'0'];}else if('name'in trace&&(posAxis.type==='category'||isNumeric(trace.name)&&['linear','log'].indexOf(posAxis.type)!==-1||Lib.isDateTime(trace.name)&&posAxis.type==='date')){pos0=trace.name;}else{pos0=num;}var pos0c=posAxis.type==='multicategory'?posAxis.r2c_just_indices(pos0):posAxis.d2c(pos0,0,trace[posLetter+'calendar']);var len=trace._length;var out=new Array(len);for(var i=0;i1;var groupFraction=1-fullLayout[traceType+'gap'];var groupGapFraction=1-fullLayout[traceType+'groupgap'];for(i=0;i0;if(side==='positive'){pushplus=dPos*(width?1:0.5);edgeplus=edge;pushminus=edgeplus=bPos;}else if(side==='negative'){pushplus=edgeplus=bPos;pushminus=dPos*(width?1:0.5);edgeminus=edge;}else{pushplus=pushminus=dPos;edgeplus=edgeminus=edge;}if(hasPts){var pointpos=trace.pointpos;var jitter=trace.jitter;var ms=trace.marker.size/2;var pp=0;if(pointpos+jitter>=0){pp=edge*(pointpos+jitter);if(pp>pushplus){// (++) beyond plus-value, use pp\npadded=true;ppadplus=ms;vpadplus=pp;}else if(pp>edgeplus){// (+), use push-value (it's bigger), but add px-pad\nppadplus=ms;vpadplus=pushplus;}}if(pp<=pushplus){// (->) fallback to push value\nvpadplus=pushplus;}var pm=0;if(pointpos-jitter<=0){pm=-edge*(pointpos-jitter);if(pm>pushminus){// (--) beyond plus-value, use pp\npadded=true;ppadminus=ms;vpadminus=pm;}else if(pm>edgeminus){// (-), use push-value (it's bigger), but add px-pad\nppadminus=ms;vpadminus=pushminus;}}if(pm<=pushminus){// (<-) fallback to push value\nvpadminus=pushminus;}}else{vpadplus=pushplus;vpadminus=pushminus;}var pos=new Array(calcTrace.length);for(j=0;j0){defaultOrientation='v';if(xDims>0){len=Math.min(xLen,yLen);}else{len=Math.min(yLen);}}else if(xDims>0){defaultOrientation='h';len=Math.min(xLen);}else{len=0;}if(!len){traceOut.visible=false;return;}traceOut._length=len;var orientation=coerce('orientation',defaultOrientation);// these are just used for positioning, they never define the sample\nif(traceOut._hasPreCompStats){if(orientation==='v'&&xDims===0){coerce('x0',0);coerce('dx',1);}else if(orientation==='h'&&yDims===0){coerce('y0',0);coerce('dy',1);}}else{if(orientation==='v'&&xDims===0){coerce('x0');}else if(orientation==='h'&&yDims===0){coerce('y0');}}var handleCalendarDefaults=Registry.getComponentMethod('calendars','handleTraceDefaults');handleCalendarDefaults(traceIn,traceOut,['x','y'],layout);}function handlePointsDefaults(traceIn,traceOut,coerce,opts){var prefix=opts.prefix;var outlierColorDflt=Lib.coerce2(traceIn,traceOut,attributes,'marker.outliercolor');var lineoutliercolor=coerce('marker.line.outliercolor');var modeDflt='outliers';if(traceOut._hasPreCompStats){modeDflt='all';}else if(outlierColorDflt||lineoutliercolor){modeDflt='suspectedoutliers';}var mode=coerce(prefix+'points',modeDflt);if(mode){coerce('jitter',mode==='all'?0.3:0);coerce('pointpos',mode==='all'?-1.5:0);coerce('marker.symbol');coerce('marker.opacity');coerce('marker.size');coerce('marker.color',traceOut.line.color);coerce('marker.line.color');coerce('marker.line.width');if(mode==='suspectedoutliers'){coerce('marker.line.outliercolor',traceOut.marker.color);coerce('marker.line.outlierwidth');}coerce('selected.marker.color');coerce('unselected.marker.color');coerce('selected.marker.size');coerce('unselected.marker.size');coerce('text');coerce('hovertext');}else{delete traceOut.marker;}var hoveron=coerce('hoveron');if(hoveron==='all'||hoveron.indexOf('points')!==-1){coerce('hovertemplate');}Lib.coerceSelectionMarkerOpacity(traceOut,coerce);}function crossTraceDefaults(fullData,fullLayout){var traceIn,traceOut;function coerce(attr){return Lib.coerce(traceOut._input,traceOut,attributes,attr);}for(var i=0;id.lo){pt.so=true;}}return pts;});paths.enter().append('path').classed('point',true);paths.exit().remove();paths.call(Drawing.translatePoints,xa,ya);}function plotBoxMean(sel,axes,trace,t){var posAxis=axes.pos;var valAxis=axes.val;var bPos=t.bPos;var bPosPxOffset=t.bPosPxOffset||0;// to support violin mean lines\nvar mode=trace.boxmean||(trace.meanline||{}).visible;// to support for one-sided box\nvar bdPos0;var bdPos1;if(Array.isArray(t.bdPos)){bdPos0=t.bdPos[0];bdPos1=t.bdPos[1];}else{bdPos0=t.bdPos;bdPos1=t.bdPos;}var paths=sel.selectAll('path.mean').data(trace.type==='box'&&trace.boxmean||trace.type==='violin'&&trace.box.visible&&trace.meanline.visible?Lib.identity:[]);paths.enter().append('path').attr('class','mean').style({fill:'none','vector-effect':'non-scaling-stroke'});paths.exit().remove();paths.each(function(d){var lcenter=posAxis.c2l(d.pos+bPos,true);var posc=posAxis.l2p(lcenter)+bPosPxOffset;var pos0=posAxis.l2p(lcenter-bdPos0)+bPosPxOffset;var pos1=posAxis.l2p(lcenter+bdPos1)+bPosPxOffset;var m=valAxis.c2p(d.mean,true);var sl=valAxis.c2p(d.mean-d.sd,true);var sh=valAxis.c2p(d.mean+d.sd,true);if(trace.orientation==='h'){d3.select(this).attr('d','M'+m+','+pos0+'V'+pos1+(mode==='sd'?'m0,0L'+sl+','+posc+'L'+m+','+pos0+'L'+sh+','+posc+'Z':''));}else{d3.select(this).attr('d','M'+pos0+','+m+'H'+pos1+(mode==='sd'?'m0,0L'+posc+','+sl+'L'+pos0+','+m+'L'+posc+','+sh+'Z':''));}});}module.exports={plot:plot,plotBoxAndWhiskers:plotBoxAndWhiskers,plotPoints:plotPoints,plotBoxMean:plotBoxMean};},{\"../../components/drawing\":624,\"../../lib\":735,\"d3\":165}],911:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';module.exports=function selectPoints(searchInfo,selectionTester){var cd=searchInfo.cd;var xa=searchInfo.xaxis;var ya=searchInfo.yaxis;var selection=[];var i,j;if(selectionTester===false){for(i=0;i=10){return null;}var min=Infinity;var max=-Infinity;var n=a.length;for(var i=0;i0?Math.floor:Math.ceil;var dirceil=dir>0?Math.ceil:Math.floor;var dirmin=dir>0?Math.min:Math.max;var dirmax=dir>0?Math.max:Math.min;var idx0=dirfloor(vstart+tol);var idx1=dirceil(vend-tol);p0=xy(vstart);var segments=[[p0]];for(idx=idx0;idx*dir=0;i--){x[nea1-i]=xctrl[neb1][i];y[nea1-i]=yctrl[neb1][i];}segments.push({x:x,y:y,bicubic:asmoothing});// Backwards along the lower b axis:\nfor(i=neb1,x=[],y=[];i>=0;i--){x[neb1-i]=xctrl[i][0];y[neb1-i]=yctrl[i][0];}segments.push({x:x,y:y,bicubic:bsmoothing});return segments;};},{}],925:[function(_dereq_,module,exports){/**\n* Copyright 2012-2020, Plotly, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the MIT license found in the\n* LICENSE file in the root directory of this source tree.\n*/'use strict';var Axes=_dereq_('../../plots/cartesian/axes');var extendFlat=_dereq_('../../lib/extend').extendFlat;module.exports=function calcGridlines(trace,axisLetter,crossAxisLetter){var i,j,j0;var eps,bounds,n1,n2,n,value,v;var j1,v0,v1,d;var data=trace['_'+axisLetter];var axis=trace[axisLetter+'axis'];var gridlines=axis._gridlines=[];var minorgridlines=axis._minorgridlines=[];var boundarylines=axis._boundarylines=[];var crossData=trace['_'+crossAxisLetter];var crossAxis=trace[crossAxisLetter+'axis'];if(axis.tickmode==='array'){axis.tickvals=data.slice();}var xcp=trace._xctrl;var ycp=trace._yctrl;var nea=xcp[0].length;var neb=xcp.length;var na=trace._a.length;var nb=trace._b.length;Axes.prepTicks(axis);// don't leave tickvals in axis looking like an attribute\nif(axis.tickmode==='array')delete axis.tickvals;// The default is an empty array that will cause the join to remove the gridline if\n// it's just disappeared:\n// axis._startline = axis._endline = [];\n// If the cross axis uses bicubic interpolation, then the grid\n// lines fall once every three expanded grid row/cols:\nvar stride=axis.smoothing?3:1;function constructValueGridline(value){var i,j,j0,tj,pxy,i0,ti,xy,dxydi0,dxydi1,dxydj0,dxydj1;var xpoints=[];var ypoints=[];var ret={};// Search for the fractional grid index giving this line:\nif(axisLetter==='b'){// For the position we use just the i-j coordinates:\nj=trace.b2j(value);// The derivatives for catmull-rom splines are discontinuous across cell\n// boundaries though, so we need to provide both the cell and the position\n// within the cell separately:\nj0=Math.floor(Math.max(0,Math.min(nb-2,j)));tj=j-j0;ret.length=nb;ret.crossLength=na;ret.xy=function(i){return trace.evalxy([],i,j);};ret.dxy=function(i0,ti){return trace.dxydi([],i0,j0,ti,tj);};for(i=0;i0){// First control point:\ndxydi0=trace.dxydi([],i-1,j0,0,tj);xpoints.push(pxy[0]+dxydi0[0]/3);ypoints.push(pxy[1]+dxydi0[1]/3);// Second control point:\ndxydi1=trace.dxydi([],i-1,j0,1,tj);xpoints.push(xy[0]-dxydi1[0]/3);ypoints.push(xy[1]-dxydi1[1]/3);}xpoints.push(xy[0]);ypoints.push(xy[1]);pxy=xy;}}else{i=trace.a2i(value);i0=Math.floor(Math.max(0,Math.min(na-2,i)));ti=i-i0;ret.length=na;ret.crossLength=nb;ret.xy=function(j){return trace.evalxy([],i,j);};ret.dxy=function(j0,tj){return trace.dxydj([],i0,j0,ti,tj);};for(j=0;j