UNPKG

plotly-js-material-design-theme

Version:
1,574 lines (1,373 loc) 6.4 MB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else { var a = factory(); for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; } })(typeof self !== 'undefined' ? self : this, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 482); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * Copyright 2012-2018, Plotly, Inc. * All rights reserved. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var d3 = __webpack_require__(2); var isNumeric = __webpack_require__(4); var numConstants = __webpack_require__(8); var FP_SAFE = numConstants.FP_SAFE; var BADNUM = numConstants.BADNUM; var lib = module.exports = {}; lib.nestedProperty = __webpack_require__(107); lib.keyedContainer = __webpack_require__(489); lib.relativeAttr = __webpack_require__(490); lib.isPlainObject = __webpack_require__(67); lib.mod = __webpack_require__(153); lib.toLogRange = __webpack_require__(154); lib.relinkPrivateKeys = __webpack_require__(491); lib.ensureArray = __webpack_require__(492); var isArrayModule = __webpack_require__(85); lib.isTypedArray = isArrayModule.isTypedArray; lib.isArrayOrTypedArray = isArrayModule.isArrayOrTypedArray; var coerceModule = __webpack_require__(493); 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 = __webpack_require__(494); 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 = __webpack_require__(155); lib.findBin = searchModule.findBin; lib.sorterAsc = searchModule.sorterAsc; lib.sorterDes = searchModule.sorterDes; lib.distinctVals = searchModule.distinctVals; lib.roundUp = searchModule.roundUp; var statsModule = __webpack_require__(495); lib.aggNums = statsModule.aggNums; lib.len = statsModule.len; lib.mean = statsModule.mean; lib.variance = statsModule.variance; lib.stdev = statsModule.stdev; lib.interp = statsModule.interp; var matrixModule = __webpack_require__(253); 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 = __webpack_require__(252); lib.deg2rad = anglesModule.deg2rad; lib.rad2deg = anglesModule.rad2deg; lib.wrap360 = anglesModule.wrap360; lib.wrap180 = anglesModule.wrap180; var geom2dModule = __webpack_require__(496); 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 = __webpack_require__(7); lib.extendFlat = extendModule.extendFlat; lib.extendDeep = extendModule.extendDeep; lib.extendDeepAll = extendModule.extendDeepAll; lib.extendDeepNoArrays = extendModule.extendDeepNoArrays; var loggersModule = __webpack_require__(86); lib.log = loggersModule.log; lib.warn = loggersModule.warn; lib.error = loggersModule.error; var regexModule = __webpack_require__(110); lib.counterRegex = regexModule.counter; var throttleModule = __webpack_require__(156); lib.throttle = throttleModule.throttle; lib.throttleDone = throttleModule.done; lib.clearThrottle = throttleModule.clear; lib.getGraphDiv = __webpack_require__(254); lib._ = __webpack_require__(497); lib.notifier = __webpack_require__(498); lib.filterUnique = __webpack_require__(499); lib.filterVisible = __webpack_require__(500); lib.pushUnique = __webpack_require__(248); lib.cleanNumber = __webpack_require__(501); lib.ensureNumber = function num(v) { if(!isNumeric(v)) return BADNUM; v = Number(v); if(v < -FP_SAFE || v > FP_SAFE) return BADNUM; return isNumeric(v) ? Number(v) : BADNUM; }; lib.noop = __webpack_require__(152); lib.identity = __webpack_require__(255); /** * swap x and y of the same attribute in container cont * specify attr with a ? in place of x/y * you can also swap other things than x/y by providing part1 and part2 */ lib.swapAttrs = function(cont, attrList, part1, part2) { if(!part1) part1 = 'x'; if(!part2) part2 = 'y'; for(var i = 0; i < attrList.length; i++) { var attr = attrList[i], xp = lib.nestedProperty(cont, attr.replace('?', part1)), yp = lib.nestedProperty(cont, attr.replace('?', part2)), temp = xp.get(); xp.set(yp.get()); yp.set(temp); } }; /** * SVG painter's algo worked around with reinsertion */ lib.raiseToTop = function raiseToTop(elem) { elem.parentNode.appendChild(elem); }; /** * cancel a possibly pending transition; returned selection may be used by caller */ lib.cancelTransition = function(selection) { return selection.transition().duration(0); }; // constrain - restrict a number v to be between v0 and v1 lib.constrain = function(v, v0, v1) { if(v0 > v1) return Math.max(v1, Math.min(v0, v)); return Math.max(v0, Math.min(v1, v)); }; /** * do two bounding boxes from getBoundingClientRect, * ie {left,right,top,bottom,width,height}, overlap? * takes optional padding pixels */ 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); }; /* * simpleMap: alternative to Array.map that only * passes on the element and up to 2 extra args you * provide (but not the array index or the whole array) * * array: the array to map it to * func: the function to apply * x1, x2: optional extra args */ lib.simpleMap = function(array, func, x1, x2) { var len = array.length, out = new Array(len); for(var i = 0; i < len; i++) out[i] = func(array[i], x1, x2); return out; }; // random string generator lib.randstr = function randstr(existing, bits, base) { /* * Include number of bits, the base of the string you want * and an optional array of existing strings to avoid. */ if(!base) base = 16; if(bits === undefined) bits = 24; if(bits <= 0) return '0'; var digits = Math.log(Math.pow(2, bits)) / Math.log(base), res = '', i, b, x; for(i = 2; digits === Infinity; i *= 2) { digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i; } var rem = digits - Math.floor(digits); for(i = 0; i < Math.floor(digits); i++) { x = Math.floor(Math.random() * base).toString(base); res = x + res; } if(rem) { b = Math.pow(base, rem); x = Math.floor(Math.random() * b).toString(base); res = x + res; } var parsed = parseInt(res, base); if((existing && (existing.indexOf(res) > -1)) || (parsed !== Infinity && parsed >= Math.pow(2, bits))) { return randstr(existing, bits, base); } else return res; }; lib.OptionControl = function(opt, optname) { /* * An environment to contain all option setters and * getters that collectively modify opts. * * You can call up opts from any function in new object * as this.optname || this.opt * * See FitOpts for example of usage */ 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; }; /** * lib.smooth: smooth arrayIn by convolving with * a hann window with given full width at half max * bounce the ends in, so the output has the same length as the input */ lib.smooth = function(arrayIn, FWHM) { FWHM = Math.round(FWHM) || 0; // only makes sense for integers if(FWHM < 2) return arrayIn; var alen = arrayIn.length, alen2 = 2 * alen, wlen = 2 * FWHM - 1, w = new Array(wlen), arrayOut = new Array(alen), i, j, k, v; // first make the window array for(i = 0; i < wlen; i++) { w[i] = (1 - Math.cos(Math.PI * (i + 1) / FWHM)) / (2 * FWHM); } // now do the convolution for(i = 0; i < alen; i++) { v = 0; for(j = 0; j < wlen; j++) { k = i + j + 1 - FWHM; // multibounce if(k < -alen) k -= alen2 * Math.round(k / alen2); else if(k >= alen2) k -= alen2 * Math.floor(k / alen2); // single bounce if(k < 0) k = - 1 - k; else if(k >= alen) k = alen2 - 1 - k; v += arrayIn[k] * w[j]; } arrayOut[i] = v; } return arrayOut; }; /** * syncOrAsync: run a sequence of functions synchronously * as long as its returns are not promises (ie have no .then) * includes one argument arg to send to all functions... * this is mainly just to prevent us having to make wrapper functions * when the only purpose of the wrapper is to reference gd * and a final step to be executed at the end * TODO: if there's an error and everything is sync, * this doesn't happen yet because we want to make sure * that it gets reported */ 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); }; /** * Helper to strip trailing slash, from * http://stackoverflow.com/questions/6680825/return-string-without-trailing-slash */ lib.stripTrailingSlash = function(str) { if(str.substr(-1) === '/') return str.substr(0, str.length - 1); return str; }; lib.noneOrAll = function(containerIn, containerOut, attrList) { /** * some attributes come together, so if you have one of them * in the input, you should copy the default values of the others * to the input as well. */ if(!containerIn) return; var hasAny = false, hasAll = true, i, val; for(i = 0; i < attrList.length; i++) { val = containerIn[attrList[i]]; if(val !== undefined && val !== null) hasAny = true; else hasAll = false; } if(hasAny && !hasAll) { for(i = 0; i < attrList.length; i++) { containerIn[attrList[i]] = containerOut[attrList[i]]; } } }; /** merges calcdata field (given by cdAttr) with traceAttr values * * N.B. Loop over minimum of cd.length and traceAttr.length * i.e. it does not try to fill in beyond traceAttr.length-1 * * @param {array} traceAttr : trace attribute * @param {object} cd : calcdata trace * @param {string} cdAttr : calcdata key */ lib.mergeArray = function(traceAttr, cd, cdAttr) { if(lib.isArrayOrTypedArray(traceAttr)) { var imax = Math.min(traceAttr.length, cd.length); for(var i = 0; i < imax; i++) cd[i][cdAttr] = traceAttr[i]; } }; /** fills calcdata field (given by cdAttr) with traceAttr values * or function of traceAttr values (e.g. some fallback) * * N.B. Loops over all cd items. * * @param {array} traceAttr : trace attribute * @param {object} cd : calcdata trace * @param {string} cdAttr : calcdata key * @param {function} [fn] : optional function to apply to each array item */ lib.fillArray = function(traceAttr, cd, cdAttr, fn) { fn = fn || lib.identity; if(lib.isArrayOrTypedArray(traceAttr)) { for(var i = 0; i < cd.length; i++) { cd[i][cdAttr] = fn(traceAttr[i]); } } }; /** Handler for trace-wide vs per-point options * * @param {object} trace : (full) trace object * @param {number} ptNumber : index of the point in question * @param {string} astr : attribute string * @param {function} [fn] : optional function to apply to each array item * * @return {any} */ lib.castOption = function(trace, ptNumber, astr, fn) { fn = fn || lib.identity; var val = lib.nestedProperty(trace, astr).get(); if(lib.isArrayOrTypedArray(val)) { if(Array.isArray(ptNumber) && lib.isArrayOrTypedArray(val[ptNumber[0]])) { return fn(val[ptNumber[0]][ptNumber[1]]); } else { return fn(val[ptNumber]); } } else { return val; } }; /** Extract option from calcdata item, correctly falling back to * trace value if not found. * * @param {object} calcPt : calcdata[i][j] item * @param {object} trace : (full) trace object * @param {string} calcKey : calcdata key * @param {string} traceKey : aka trace attribute string * @return {any} */ lib.extractOption = function(calcPt, trace, calcKey, traceKey) { if(calcKey in calcPt) return calcPt[calcKey]; // fallback to trace value, // must check if value isn't itself an array // which means the trace attribute has a corresponding // calcdata key, but its value is falsy var traceVal = lib.nestedProperty(trace, traceKey).get(); if(!Array.isArray(traceVal)) return traceVal; }; /** Tag selected calcdata items * * N.B. note that point 'index' corresponds to input data array index * whereas 'number' is its post-transform version. * * @param {array} calcTrace * @param {object} trace * - selectedpoints {array} * - _indexToPoints {object} * @param {ptNumber2cdIndex} ptNumber2cdIndex (optional) * optional map object for trace types that do not have 1-to-1 point number to * calcdata item index correspondence (e.g. histogram) */ lib.tagSelected = function(calcTrace, trace, ptNumber2cdIndex) { var selectedpoints = trace.selectedpoints; var indexToPoints = trace._indexToPoints; var ptIndex2ptNumber; // make pt index-to-number map object, which takes care of transformed traces if(indexToPoints) { ptIndex2ptNumber = {}; for(var k in indexToPoints) { var pts = indexToPoints[k]; for(var j = 0; j < pts.length; j++) { ptIndex2ptNumber[pts[j]] = k; } } } function isPtIndexValid(v) { return isNumeric(v) && v >= 0 && v % 1 === 0; } function isCdIndexValid(v) { return v !== undefined && v < calcTrace.length; } for(var i = 0; i < selectedpoints.length; i++) { var ptIndex = selectedpoints[i]; if(isPtIndexValid(ptIndex)) { var ptNumber = ptIndex2ptNumber ? ptIndex2ptNumber[ptIndex] : ptIndex; var cdIndex = ptNumber2cdIndex ? ptNumber2cdIndex[ptNumber] : ptNumber; if(isCdIndexValid(cdIndex)) { calcTrace[cdIndex].selected = 1; } } } }; /** Returns target as set by 'target' transform attribute * * @param {object} trace : full trace object * @param {object} transformOpts : transform option object * - target (string} : * either an attribute string referencing an array in the trace object, or * a set array. * * @return {array or false} : the target array (NOT a copy!!) or false if invalid */ lib.getTargetArray = function(trace, transformOpts) { var target = transformOpts.target; if(typeof target === 'string' && target) { var array = lib.nestedProperty(trace, target).get(); return Array.isArray(array) ? array : false; } else if(Array.isArray(target)) { return target; } return false; }; /** * modified version of jQuery's extend to strip out private objs and functions, * and cut arrays down to first <arraylen> or 1 elements * because extend-like algorithms are hella slow * obj2 is assumed to already be clean of these things (including no arrays) */ lib.minExtend = function(obj1, obj2) { var objOut = {}; if(typeof obj2 !== 'object') obj2 = {}; var arrayLen = 3, keys = Object.keys(obj1), i, k, v; for(i = 0; i < keys.length; i++) { k = keys[i]; v = obj1[k]; if(k.charAt(0) === '_' || typeof v === 'function') continue; else if(k === 'module') objOut[k] = v; else if(Array.isArray(v)) objOut[k] = v.slice(0, arrayLen); else if(v && (typeof v === 'object')) objOut[k] = lib.minExtend(obj1[k], obj2[k]); else objOut[k] = v; } keys = Object.keys(obj2); for(i = 0; i < keys.length; i++) { k = keys[i]; v = obj2[k]; if(typeof v !== 'object' || !(k in objOut) || typeof objOut[k] !== 'object') { objOut[k] = v; } } return objOut; }; lib.titleCase = function(s) { return s.charAt(0).toUpperCase() + s.substr(1); }; lib.containsAny = function(s, fragments) { for(var i = 0; i < fragments.length; i++) { if(s.indexOf(fragments[i]) !== -1) return true; } return false; }; lib.isPlotDiv = function(el) { var el3 = d3.select(el); return el3.node() instanceof HTMLElement && el3.size() && el3.classed('js-plotly-plot'); }; lib.removeElement = function(el) { var elParent = el && el.parentNode; if(elParent) elParent.removeChild(el); }; /** * for dynamically adding style rules * makes one stylesheet that contains all rules added * by all calls to this function */ lib.addStyleRule = function(selector, styleString) { if(!lib.styleSheet) { var style = document.createElement('style'); // WebKit hack :( style.appendChild(document.createTextNode('')); document.head.appendChild(style); lib.styleSheet = style.sheet; } var styleSheet = lib.styleSheet; if(styleSheet.insertRule) { styleSheet.insertRule(selector + '{' + styleString + '}', 0); } else if(styleSheet.addRule) { styleSheet.addRule(selector, styleString, 0); } else lib.warn('addStyleRule failed'); }; lib.isIE = function() { return typeof window.navigator.msSaveBlob !== 'undefined'; }; /** * Duck typing to recognize a d3 selection, mostly for IE9's benefit * because it doesn't handle instanceof like modern browsers */ lib.isD3Selection = function(obj) { return obj && (typeof obj.classed === 'function'); }; /** * Converts a string path to an object. * * When given a string containing an array element, it will create a `null` * filled array of the given size. * * @example * lib.objectFromPath('nested.test[2].path', 'value'); * // returns { nested: { test: [null, null, { path: 'value' }]} * * @param {string} path to nested value * @param {*} any value to be set * * @return {Object} the constructed object with a full nested path */ lib.objectFromPath = function(path, value) { var keys = path.split('.'), tmpObj, obj = tmpObj = {}; for(var i = 0; i < keys.length; i++) { var key = keys[i]; var el = null; var parts = keys[i].match(/(.*)\[([0-9]+)\]/); if(parts) { key = parts[1]; el = parts[2]; tmpObj = tmpObj[key] = []; if(i === keys.length - 1) { tmpObj[el] = value; } else { tmpObj[el] = {}; } tmpObj = tmpObj[el]; } else { if(i === keys.length - 1) { tmpObj[key] = value; } else { tmpObj[key] = {}; } tmpObj = tmpObj[key]; } } return obj; }; /** * Iterate through an object in-place, converting dotted properties to objects. * * Examples: * * lib.expandObjectPaths({'nested.test.path': 'value'}); * => { nested: { test: {path: 'value'}}} * * It also handles array notation, e.g.: * * lib.expandObjectPaths({'foo[1].bar': 'value'}); * => { foo: [null, {bar: value}] } * * It handles merges the results when two properties are specified in parallel: * * lib.expandObjectPaths({'foo[1].bar': 10, 'foo[0].bar': 20}); * => { foo: [{bar: 10}, {bar: 20}] } * * It does NOT, however, merge mulitple mutliply-nested arrays:: * * lib.expandObjectPaths({'marker[1].range[1]': 5, 'marker[1].range[0]': 4}) * => { marker: [null, {range: 4}] } */ // Store this to avoid recompiling regex on *every* prop since this may happen many // many times for animations. Could maybe be inside the function. Not sure about // scoping vs. recompilation tradeoff, but at least it's not just inlining it into // the inner loop. var 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 // we must recurse, e.g. transforms[0].value trailingPath = match[4]; dest = data[prop][idx] = data[prop][idx] || {}; // NB: Extend deep no arrays prevents this from working on multiple // nested properties in the same object, e.g. // // { // foo[0].bar[1].range // foo[0].bar[0].range // } // // In this case, the extendDeepNoArrays will overwrite one array with // the other, so that both properties *will not* be present in the // result. Fixing this would require a more intelligent tracking // of changes and merging than extendDeepNoArrays currently accomplishes. lib.extendDeepNoArrays(dest, lib.objectFromPath(trailingPath, lib.expandObjectPaths(datum))); } else { // This is the case where this property is the end of the line, // e.g. xaxis.range[0] data[prop][idx] = lib.expandObjectPaths(datum); } } else { data[key] = lib.expandObjectPaths(data[key]); } } } } return data; }; /** * Converts value to string separated by the provided separators. * * @example * lib.numSeparate(2016, '.,'); * // returns '2016' * * @example * lib.numSeparate(3000, '.,', true); * // returns '3,000' * * @example * lib.numSeparate(1234.56, '|,') * // returns '1,234|56' * * @param {string|number} value the value to be converted * @param {string} separators string of decimal, then thousands separators * @param {boolean} separatethousands boolean, 4-digit integers are separated if true * * @return {string} the value that has been separated */ 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})/, decimalSep = separators.charAt(0), thouSep = separators.charAt(1); var x = value.split('.'), x1 = x[0], x2 = x.length > 1 ? decimalSep + x[1] : ''; // Years are ignored for thousands separators if(thouSep && (x.length > 1 || x1.length > 4 || separatethousands)) { while(thousandsRe.test(x1)) { x1 = x1.replace(thousandsRe, '$1' + thouSep + '$2'); } } return x1 + x2; }; var TEMPLATE_STRING_REGEX = /%{([^\s%{}]*)}/g; var SIMPLE_PROPERTY_REGEX = /^\w*$/; /* * Substitute values from an object into a string * * Examples: * Lib.templateString('name: %{trace}', {trace: 'asdf'}) --> 'name: asdf' * Lib.templateString('name: %{trace[0].name}', {trace: [{name: 'asdf'}]}) --> 'name: asdf' * * @param {string} input string containing %{...} template strings * @param {obj} data object containing substitution values * * @return {string} templated string */ lib.templateString = function(string, obj) { // Not all that useful, but cache nestedProperty instantiation // just in case it speeds things up *slightly*: var getterCache = {}; return string.replace(TEMPLATE_STRING_REGEX, function(dummy, key) { if(SIMPLE_PROPERTY_REGEX.test(key)) { return obj[key] || ''; } getterCache[key] = getterCache[key] || lib.nestedProperty(obj, key).get; return getterCache[key]() || ''; }); }; /* * alphanumeric string sort, tailored for subplot IDs like scene2, scene10, x10y13 etc */ var char0 = 48; var char9 = 57; lib.subplotSort = function(a, b) { var l = Math.min(a.length, b.length) + 1; var numA = 0; var numB = 0; for(var i = 0; i < l; i++) { var charA = a.charCodeAt(i) || 0; var charB = b.charCodeAt(i) || 0; var isNumA = charA >= 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 var 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 // gets away from really trying to be random, in favor of better local uniformity if(Math.abs(randSeed - lastVal) < 429496729) return lib.pseudoRandom(); return randSeed / 4294967296; }; /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * Copyright 2012-2018, Plotly, Inc. * All rights reserved. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var Loggers = __webpack_require__(86); var noop = __webpack_require__(152); var pushUnique = __webpack_require__(248); var isPlainObject = __webpack_require__(67); var ExtendModule = __webpack_require__(7); var basePlotAttributes = __webpack_require__(25); var baseLayoutAttributes = __webpack_require__(68); 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 = {}; /** * Top-level register routine, exported as Plotly.register * * @param {object array or array of objects} _modules : * module object or list of module object to register. * * A valid `moduleType: 'trace'` module has fields: * - name {string} : the trace type * - categories {array} : categories associated with this trace type, * tested with Register.traceIs() * - meta {object} : meta info (mostly for plot-schema) * * A valid `moduleType: 'locale'` module has fields: * - name {string} : the locale name. Should be a 2-digit language string ('en', 'de') * optionally with a country/region code ('en-GB', 'de-CH'). If a country * code is used but the base language locale has not yet been supplied, * we will use this locale for the base as well. * - dictionary {object} : the dictionary mapping input strings to localized strings * generally the keys should be the literal input strings, but * if default translations are provided you can use any string as a key. * - format {object} : a `d3.locale` format specifier for this locale * any omitted keys we'll fall back on en-US. * * A valid `moduleType: 'transform'` module has fields: * - name {string} : transform name * - transform {function} : default-level transform function * - calcTransform {function} : calc-level transform function * - attributes {object} : transform attributes declarations * - supplyDefaults {function} : attributes default-supply function * * A valid `moduleType: 'component'` module has fields: * - name {string} : the component name, used it with Register.getComponentMethod() * to employ component method. * * A valid `moduleType: 'apiMethod'` module has fields: * - name {string} : the api method name. * - fn {function} : the api method called with Register.call(); * */ exports.register = function register(_modules) { 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!'); } } }; /** * Get registered module using trace object or trace type * * @param {object||string} trace * trace object with prop 'type' or trace type as a string * @return {object} * module object corresponding to trace type */ exports.getModule = function(trace) { var _module = exports.modules[getTraceType(trace)]; if(!_module) return false; return _module._module; }; /** * Determine if this trace type is in a given category * * @param {object||string} traceType * a trace (object) or trace type (string) * @param {string} category * category in question * @return {boolean} */ exports.traceIs = function(traceType, category) { traceType = getTraceType(traceType); // old plot.ly workspace hack, nothing to see here if(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]; }; /** * Determine if this trace has a transform of the given type and return * array of matching indices. * * @param {object} data * a trace object (member of data or fullData) * @param {string} type * type of trace to test * @return {array} * array of matching indices. If none found, returns [] */ exports.getTransformIndices = function(data, type) { var indices = []; var transforms = data.transforms || []; for(var i = 0; i < transforms.length; i++) { if(transforms[i].type === type) { indices.push(i); } } return indices; }; /** * Determine if this trace has a transform of the given type * * @param {object} data * a trace object (member of data or fullData) * @param {string} type * type of trace to test * @return {boolean} */ exports.hasTransform = function(data, type) { var transforms = data.transforms || []; for(var i = 0; i < transforms.length; i++) { if(transforms[i].type === type) { return true; } } return false; }; /** * Retrieve component module method. Falls back on noop if either the * module or the method is missing, so the result can always be safely called * * @param {string} name * name of component (as declared in component module) * @param {string} method * name of component module method * @return {function} */ exports.getComponentMethod = function(name, method) { var _module = exports.componentsRegistry[name]; if(!_module) return noop; return _module[method] || noop; }; /** * Call registered api method. * * @param {string} name : api method name * @param {...array} args : arguments passed to api method * @return {any} : returns api method output */ exports.call = function() { var name = arguments[0]; var args = [].slice.call(arguments, 1); return exports.apiMethodRegistry[name].apply(null, args); }; function registerTraceModule(_module) { var thisType = _module.name; var categoriesIn = _module.categories; var meta = _module.meta; if(exports.modules[thisType]) { Loggers.log('Type ' + thisType + ' already registered'); return; } if(!exports.subplotsRegistry[_module.basePlotModule.name]) { registerSubplot(_module.basePlotModule); } var categoryObj = {}; for(var i = 0; i < categoriesIn.length; i++) { categoryObj[categoriesIn[i]] = true; exports.allCategories[categoriesIn[i]] = true; } exports.modules[thisType] = { _module: _module, categories: categoryObj }; if(meta && Object.keys(meta).length) { exports.modules[thisType].meta = meta; } exports.allTypes.push(thisType); for(var componentName in exports.componentsRegistry) { mergeComponentAttrsToTrace(componentName, thisType); } /* * Collect all trace layout attributes in one place for easier lookup later * but don't merge them into the base schema as it would confuse the docs * (at least after https://github.com/plotly/documentation/issues/202 gets done!) */ if(_module.layoutAttributes) { extendFlat(exports.traceLayoutAttributes, _module.layoutAttributes); } } function registerSubplot(_module) { var plotType = _module.name; if(exports.subplotsRegistry[plotType]) { Loggers.log('Plot type ' + plotType + ' already registered.'); return; } // relayout array handling will look for component module methods with this // name and won't find them because this is a subplot module... but that // should be fine, it will just fall back on redrawing the plot. findArrayRegexps(_module); // not sure what's best for the 'cartesian' type at this point exports.subplotsRegistry[plotType] = _module; for(var componentName in exports.componentsRegistry) { mergeComponentAttrsToSubplot(componentName, _module.name); } } function registerComponentModule(_module) { if(typeof _module.name !== 'string') { throw new Error('Component module *name* must be a string.'); } var name = _module.name; exports.componentsRegistry[name] = _module; if(_module.layoutAttributes) { if(_module.layoutAttributes._isLinkedToArray) { pushUnique(exports.layoutArrayContainers, name); } findArrayRegexps(_module); } for(var traceType in exports.modules) { mergeComponentAttrsToTrace(name, traceType); } for(var subplotName in exports.subplotsRegistry) { mergeComponentAttrsToSubplot(name, subplotName); } for(var transformType in exports.transformsRegistry) { mergeComponentAttrsToTransform(name, transformType); } if(_module.schema && _module.schema.layout) { extendDeepAll(baseLayoutAttributes, _module.schema.layout); } } function registerTransformModule(_module) { if(typeof _module.name !== 'string') { throw new Error('Transform module *name* must be a string.'); } var prefix = 'Transform module ' + _module.name; var hasTransform = typeof _module.transform === 'function'; var hasCalcTransform = typeof _module.calcTransform === 'function'; if(!hasTransform && !hasCalcTransform) { throw new Error(prefix + ' is missing a *transform* or *calcTransform* method.'); } if(hasTransform && hasCalcTransform) { Loggers.log([ prefix + ' has both a *transform* and *calcTransform* methods.', 'Please note that all *transform* methods are executed', 'before all *calcTransform* methods.' ].join(' ')); } if(!isPlainObject(_module.attributes)) { Loggers.log(prefix + ' registered without an *attributes* object.'); } if(typeof _module.supplyDefaults !== 'function') { Loggers.log(prefix + ' registered without a *supplyDefaults* method.'); } exports.transformsRegistry[_module.name] = _module; for(var componentName in exports.componentsRegistry) { mergeComponentAttrsToTransform(componentName, _module.name); } } function registerLocale(_module) { var locale = _module.name; var baseLocale = locale.split('-')[0]; var newDict = _module.dictionary; var newFormat = _module.format; var hasDict = newDict && Object.keys(newDict).length; var hasFormat = newFormat && Object.keys(newFormat).length; var locales = exports.localeRegistry; var localeObj = locales[locale]; if(!localeObj) locales[locale] = localeObj = {}; // Should we use this dict for the base locale? // In case we're overwriting a previous dict for this locale, check // whether the base matches the full locale dict now. If we're not // overwriting, locales[locale] is undefined so this just checks if // baseLocale already had a dict or not. // Same logic for dateFormats if(baseLocale !== locale) { var baseLocaleObj = locales[baseLocale]; if(!baseLocaleObj) locales[baseLocale] = baseLocaleObj = {}; if(hasDict && baseLocaleObj.dictionary === localeObj.dictionary) { baseLocaleObj.dictionary = newDict; } if(hasFormat && baseLocaleObj.format === localeObj.format) { baseLocaleObj.format = newFormat; } } if(hasDict) localeObj.dictionary = newDict; if(hasFormat) localeObj.format = newFormat; } function findArrayRegexps(_module) { if(_module.layoutAttributes) { var arrayAttrRegexps = _module.layoutAttributes._arrayAttrRegexps; if(arrayAttrRegexps) { for(var i = 0; i < arrayAttrRegexps.length; i++) { pushUnique(exports.layoutArrayRegexes, arrayAttrRegexps[i]); } } } } function mergeComponentAttrsToTrace(componentName, traceType) { var componentSchema = exports.componentsRegistry[componentName].schema; if(!componentSchema || !componentSchema.traces) return; var traceAttrs = componentSchema.traces[traceType]; if(traceAttrs) { extendDeepAll(exports.modules[traceType]._module.attributes, traceAttrs); } } function mergeComponentAttrsToTransform(componentName, transformType) { var componentSchema = exports.componentsRegistry[componentName].schema; if(!componentSchema || !componentSchema.transforms) return; var transformAttrs = componentSchema.transforms[transformType]; if(transformAttrs) { extendDeepAll(exports.transformsRegistry[transformType].attributes, transformAttrs); } } function mergeComponentAttrsToSubplot(componentName, subplotName) { var componentSchema = exports.componentsRegistry[componentName].schema; if(!componentSchema || !componentSchema.subplots) return; var subplotModule = exports.subplotsRegistry[subplotName]; var subplotAttrs = subplotModule.layoutAttributes; var subplotAttr = subplotModule.attr === 'subplot' ? subplotModule.name : subplotModule.attr; if(Array.isArray(subplotAttr)) subplotAttr = subplotAttr[0]; var componentLayoutAttrs = componentSchema.subplots[subplotAttr]; if(subplotAttrs && componentLayoutAttrs) { extendDeepAll(subplotAttrs, componentLayoutAttrs); } } function getTraceType(traceType) { if(typeof traceType === 'object') traceType = traceType.type; return traceType; } /***/ }), /* 2 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;!function() { var d3 = { version: "3.5.17" }; var d3_arraySlice = [].slice, d3_array = function(list) { return d3_arraySlice.call(list); }; var d3_document = this.document; function d3_documentElement(node) { return node && (node.ownerDocument || node.document || node).documentElement; } function d3_window(node) { return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView); } if (d3_document) { try { d3_array(d3_document.documentElement.childNodes)[0].nodeType; } catch (e) { d3_array = function(list) { var i = list.length, array = new Array(i); while (i--) array[i] = list[i]; return array; }; } } if (!Date.now) Date.now = function() { return +new Date(); }; if (d3_document) { try { d3_document.createElement("DIV").style.setProperty("opacity", 0, ""); } catch (error) { var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; d3_element_prototype.setAttribute = function(name, value) { d3_element_setAttribute.call(this, name, value + ""); }; d3_element_prototype.setAttributeNS = function(space, local, value) { d3_element_setAttributeNS.call(this, space, local, value + ""); }; d3_style_prototype.setProperty = function(name, value, priority) { d3_style_setProperty.call(this, name, value + "", priority); }; } } d3.ascending = d3_ascending; function d3_ascending(a, b) { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; } d3.descending = function(a, b) { return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; }; d3.min = function(array, f) { var i = -1, n = array.length, a, b; if (arguments.length === 1) { while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; } while (++i < n) if ((b = array[i]) != null && a > b) a = b; } else { while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { a = b; break; } while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; } return a; }; d3.max = function(array, f) { var i = -1, n = array.length, a, b; if (arguments.length === 1) { while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; } while (++i < n) if ((b = array[i]) != null && b > a) a = b; } else { while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { a = b; break; } while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; } return a; }; d3.extent = function(array, f) { var i = -1, n = array.length, a, b, c; if (arguments.length === 1) { while (++i < n) if ((b = array[i]) != null && b >= b) { a = c = b; break; } while (++i < n) if ((b = array[i]) != null) { if (a > b) a = b; if (c < b) c = b; } } else { while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { a = c = b; break; } while (++i < n) if ((b = f.call(array, array[i], i)) != null) { if (a > b) a = b; if (c < b) c = b; } } return [ a, c ]; }; function d3_number(x) { return x === null ? NaN : +x; } function d3_numeric(x) { return !isNaN(x); } d3.sum = function(array, f) { var s = 0, n = array.length, a, i = -1; if (arguments.length === 1) { while (++i < n) if (d3_numeric(a = +array[i])) s += a; } else { while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a; } return s; }; d3.mean = function(array, f) { var s = 0, n = array.length, a, i = -1, j = n; if (arguments.length === 1) { while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j; } else { while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j; } if (j) return s / j; }; d3.quantile = function(values, p) { var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; return e ? v + e * (values[h] - v) : v; }; d3.median = function(array, f) { var numbers = [], n = array.length, a, i = -1; if (arguments.length === 1) { while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a); } else { while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a); } if (numbers.length) return d3.quantile(numbers.