plotly-js-material-design-theme
Version:
Plotly.js charts with Material Design theme.
1,574 lines (1,373 loc) • 6.4 MB
JavaScript
(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.