- * @param {object} opts (see ../plot_api/to_image)
- * @return {promise}
- */
-function downloadImage(gd, opts) {
- var _gd;
- if(!Lib.isPlainObject(gd)) _gd = Lib.getGraphDiv(gd);
-
- // check for undefined opts
- opts = opts || {};
- // default to png
- opts.format = opts.format || 'png';
-
- return new Promise(function(resolve, reject) {
- if(_gd && _gd._snapshotInProgress) {
- reject(new Error('Snapshotting already in progress.'));
- }
-
- // see comments within svgtoimg for additional
- // discussion of problems with IE
- // can now draw to canvas, but CORS tainted canvas
- // does not allow toDataURL
- // svg format will work though
- if(Lib.isIE() && opts.format !== 'svg') {
- reject(new Error('Sorry IE does not support downloading from canvas. Try {format:\'svg\'} instead.'));
- }
-
- if(_gd) _gd._snapshotInProgress = true;
- var promise = toImage(gd, opts);
-
- var filename = opts.filename || gd.fn || 'newplot';
- filename += '.' + opts.format;
-
- promise.then(function(result) {
- if(_gd) _gd._snapshotInProgress = false;
- return fileSaver(result, filename);
- }).then(function(name) {
- resolve(name);
- }).catch(function(err) {
- if(_gd) _gd._snapshotInProgress = false;
- reject(err);
- });
- });
-}
-
-module.exports = downloadImage;
-
-},{"../lib":168,"../plot_api/to_image":205,"./filesaver":259}],259:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-/*
-* substantial portions of this code from FileSaver.js
-* https://github.com/eligrey/FileSaver.js
-* License: https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
-* FileSaver.js
-* A saveAs() FileSaver implementation.
-* 1.1.20160328
-*
-* By Eli Grey, http://eligrey.com
-* License: MIT
-* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
-*/
-
-'use strict';
-
-var fileSaver = function(url, name) {
- var saveLink = document.createElement('a');
- var canUseSaveLink = 'download' in saveLink;
- var isSafari = /Version\/[\d\.]+.*Safari/.test(navigator.userAgent);
- var promise = new Promise(function(resolve, reject) {
- // IE <10 is explicitly unsupported
- if(typeof navigator !== 'undefined' && /MSIE [1-9]\./.test(navigator.userAgent)) {
- reject(new Error('IE < 10 unsupported'));
- }
-
- // First try a.download, then web filesystem, then object URLs
- if(isSafari) {
- // Safari doesn't allow downloading of blob urls
- document.location.href = 'data:application/octet-stream' + url.slice(url.search(/[,;]/));
- resolve(name);
- }
-
- if(!name) {
- name = 'download';
- }
-
- if(canUseSaveLink) {
- saveLink.href = url;
- saveLink.download = name;
- document.body.appendChild(saveLink);
- saveLink.click();
- document.body.removeChild(saveLink);
- resolve(name);
- }
-
- // IE 10+ (native saveAs)
- if(typeof navigator !== 'undefined' && navigator.msSaveBlob) {
- // At this point we are only dealing with a SVG encoded as
- // a data URL (since IE only supports SVG)
- var encoded = url.split(/^data:image\/svg\+xml,/)[1];
- var svg = decodeURIComponent(encoded);
- navigator.msSaveBlob(new Blob([svg]), name);
- resolve(name);
- }
-
- reject(new Error('download error'));
- });
-
- return promise;
-};
-
-module.exports = fileSaver;
-
-},{}],260:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'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);
- }
- };
-};
-
-},{"../registry":256}],261:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var helpers = _dereq_('./helpers');
-
-var Snapshot = {
- getDelay: helpers.getDelay,
- getRedrawFunc: helpers.getRedrawFunc,
- clone: _dereq_('./cloneplot'),
- toSVG: _dereq_('./tosvg'),
- svgToImg: _dereq_('./svgtoimg'),
- toImage: _dereq_('./toimage'),
- downloadImage: _dereq_('./download')
-};
-
-module.exports = Snapshot;
-
-},{"./cloneplot":257,"./download":258,"./helpers":260,"./svgtoimg":262,"./toimage":263,"./tosvg":264}],262:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../lib');
-var EventEmitter = _dereq_('events').EventEmitter;
-
-function svgToImg(opts) {
- var ev = opts.emitter || new EventEmitter();
-
- var promise = new Promise(function(resolve, reject) {
- var Image = window.Image;
- var svg = opts.svg;
- var format = opts.format || 'png';
-
- // IE only support svg
- if(Lib.isIE() && format !== 'svg') {
- var ieSvgError = new Error('Sorry IE does not support downloading from canvas. Try {format:\'svg\'} instead.');
- reject(ieSvgError);
- // eventually remove the ev
- // in favor of promises
- if(!opts.promise) {
- return ev.emit('error', ieSvgError);
- } else {
- return promise;
- }
- }
-
- var canvas = opts.canvas;
- var scale = opts.scale || 1;
- var w0 = opts.width || 300;
- var h0 = opts.height || 150;
- var w1 = scale * w0;
- var h1 = scale * h0;
-
- var ctx = canvas.getContext('2d');
- var img = new Image();
-
- // for Safari support, eliminate createObjectURL
- // this decision could cause problems if content
- // is not restricted to svg
- var url = 'data:image/svg+xml,' + encodeURIComponent(svg);
-
- canvas.width = w1;
- canvas.height = h1;
-
- img.onload = function() {
- var imgData;
-
- // don't need to draw to canvas if svg
- // save some time and also avoid failure on IE
- if(format !== 'svg') {
- ctx.drawImage(img, 0, 0, w1, h1);
- }
-
- switch(format) {
- case 'jpeg':
- imgData = canvas.toDataURL('image/jpeg');
- break;
- case 'png':
- imgData = canvas.toDataURL('image/png');
- break;
- case 'webp':
- imgData = canvas.toDataURL('image/webp');
- break;
- case 'svg':
- imgData = url;
- break;
- default:
- var errorMsg = 'Image format is not jpeg, png, svg or webp.';
- reject(new Error(errorMsg));
- // eventually remove the ev
- // in favor of promises
- if(!opts.promise) {
- return ev.emit('error', errorMsg);
- }
- }
- resolve(imgData);
- // eventually remove the ev
- // in favor of promises
- if(!opts.promise) {
- ev.emit('success', imgData);
- }
- };
-
- img.onerror = function(err) {
- reject(err);
- // eventually remove the ev
- // in favor of promises
- if(!opts.promise) {
- return ev.emit('error', err);
- }
- };
-
- img.src = url;
- });
-
- // temporary for backward compatibility
- // move to only Promise in 2.0.0
- // and eliminate the EventEmitter
- if(opts.promise) {
- return promise;
- }
-
- return ev;
-}
-
-module.exports = svgToImg;
-
-},{"../lib":168,"events":15}],263:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var EventEmitter = _dereq_('events').EventEmitter;
-
-var Registry = _dereq_('../registry');
-var Lib = _dereq_('../lib');
-
-var helpers = _dereq_('./helpers');
-var clonePlot = _dereq_('./cloneplot');
-var toSVG = _dereq_('./tosvg');
-var svgToImg = _dereq_('./svgtoimg');
-
-/**
- * @param {object} gd figure Object
- * @param {object} opts option object
- * @param opts.format 'jpeg' | 'png' | 'webp' | 'svg'
- */
-function toImage(gd, opts) {
- // first clone the GD so we can operate in a clean environment
- var ev = new EventEmitter();
-
- var clone = clonePlot(gd, {format: 'png'});
- var clonedGd = clone.gd;
-
- // put the cloned div somewhere off screen before attaching to DOM
- clonedGd.style.position = 'absolute';
- clonedGd.style.left = '-5000px';
- document.body.appendChild(clonedGd);
-
- function wait() {
- var delay = helpers.getDelay(clonedGd._fullLayout);
-
- setTimeout(function() {
- var svg = toSVG(clonedGd);
-
- var canvas = document.createElement('canvas');
- canvas.id = Lib.randstr();
-
- ev = svgToImg({
- format: opts.format,
- width: clonedGd._fullLayout.width,
- height: clonedGd._fullLayout.height,
- canvas: canvas,
- emitter: ev,
- svg: svg
- });
-
- ev.clean = function() {
- if(clonedGd) document.body.removeChild(clonedGd);
- };
- }, delay);
- }
-
- var redrawFunc = helpers.getRedrawFunc(clonedGd);
-
- Registry.call('plot', clonedGd, clone.data, clone.layout, clone.config)
- .then(redrawFunc)
- .then(wait)
- .catch(function(err) {
- ev.emit('error', err);
- });
-
-
- return ev;
-}
-
-module.exports = toImage;
-
-},{"../lib":168,"../registry":256,"./cloneplot":257,"./helpers":260,"./svgtoimg":262,"./tosvg":264,"events":15}],264:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var d3 = _dereq_('d3');
-
-var Lib = _dereq_('../lib');
-var Drawing = _dereq_('../components/drawing');
-var Color = _dereq_('../components/color');
-
-var xmlnsNamespaces = _dereq_('../constants/xmlns_namespaces');
-var DOUBLEQUOTE_REGEX = /"/g;
-var DUMMY_SUB = 'TOBESTRIPPED';
-var DUMMY_REGEX = new RegExp('("' + DUMMY_SUB + ')|(' + DUMMY_SUB + '")', 'g');
-
-function htmlEntityDecode(s) {
- var hiddenDiv = d3.select('body').append('div').style({display: 'none'}).html('');
- var replaced = s.replace(/(&[^;]*;)/gi, function(d) {
- if(d === '<') { return '<'; } // special handling for brackets
- if(d === '&rt;') { return '>'; }
- if(d.indexOf('<') !== -1 || d.indexOf('>') !== -1) { return ''; }
- return hiddenDiv.html(d).text(); // everything else, let the browser decode it to unicode
- });
- 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
- // all other alterations have been dealt with by properly preparing the svg
- // in the first place... like setting cursors with css classes so we don't
- // have to remove them, and providing the right namespaces in the svg to
- // begin with
- svg.insert('rect', ':first-child')
- .call(Drawing.setRect, 0, 0, width, height)
- .call(Color.fill, fullLayout.paper_bgcolor);
-
- // subplot-specific to-SVG methods
- // which notably add the contents of the gl-container
- // into the main svg node
- var basePlotModules = fullLayout._basePlotModules || [];
- for(i = 0; i < basePlotModules.length; i++) {
- var _module = basePlotModules[i];
-
- if(_module.toSVG) _module.toSVG(gd);
- }
-
- // add top items above them assumes everything in toppaper is either
- // a group or a defs, and if it's empty (like hoverlayer) we can ignore it.
- if(toppaper) {
- var nodes = toppaper.node().childNodes;
-
- // make copy of nodes as childNodes prop gets mutated in loop below
- var topGroups = Array.prototype.slice.call(nodes);
-
- for(i = 0; i < topGroups.length; i++) {
- var topGroup = topGroups[i];
-
- if(topGroup.childNodes.length) svg.node().appendChild(topGroup);
- }
- }
-
- // remove draglayer for Adobe Illustrator compatibility
- if(fullLayout._draggers) {
- fullLayout._draggers.remove();
- }
-
- // in case the svg element had an explicit background color, remove this
- // we want the rect to get the color so it's the right size; svg bg will
- // fill whatever container it's displayed in regardless of plot size.
- svg.node().style.background = '';
-
- svg.selectAll('text')
- .attr({'data-unformatted': null, 'data-math': null})
- .each(function() {
- var txt = d3.select(this);
-
- // hidden text is pre-formatting mathjax, the browser ignores it
- // but in a static plot it's useless and it can confuse batik
- // we've tried to standardize on display:none but make sure we still
- // catch visibility:hidden if it ever arises
- if(this.style.visibility === 'hidden' || this.style.display === 'none') {
- txt.remove();
- return;
- } else {
- // clear other visibility/display values to default
- // to not potentially confuse non-browser SVG implementations
- txt.style({visibility: null, display: null});
- }
-
- // Font family styles break things because of quotation marks,
- // so we must remove them *after* the SVG DOM has been serialized
- // to a string (browsers convert singles back)
- var ff = this.style.fontFamily;
- if(ff && ff.indexOf('"') !== -1) {
- txt.style('font-family', ff.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB));
- }
- });
-
- svg.selectAll('.point, .scatterpts, .legendfill>path, .legendlines>path, .cbfill').each(function() {
- var pt = d3.select(this);
-
- // similar to font family styles above,
- // we must remove " after the SVG DOM has been serialized
- var fill = this.style.fill;
- if(fill && fill.indexOf('url(') !== -1) {
- pt.style('fill', fill.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB));
- }
-
- var stroke = this.style.stroke;
- if(stroke && stroke.indexOf('url(') !== -1) {
- pt.style('stroke', stroke.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB));
- }
- });
-
- if(format === 'pdf' || format === 'eps') {
- // these formats make the extra line MathJax adds around symbols look super thick in some cases
- // it looks better if this is removed entirely.
- svg.selectAll('#MathJax_SVG_glyphs path')
- .attr('stroke-width', 0);
- }
-
- // fix for IE namespacing quirk?
- // http://stackoverflow.com/questions/19610089/unwanted-namespaces-on-svg-markup-when-using-xmlserializer-in-javascript-with-ie
- svg.node().setAttributeNS(xmlnsNamespaces.xmlns, 'xmlns', xmlnsNamespaces.svg);
- svg.node().setAttributeNS(xmlnsNamespaces.xmlns, 'xmlns:xlink', xmlnsNamespaces.xlink);
-
- if(format === 'svg' && scale) {
- svg.attr('width', scale * width);
- svg.attr('height', scale * height);
- svg.attr('viewBox', '0 0 ' + width + ' ' + height);
- }
-
- var s = new window.XMLSerializer().serializeToString(svg.node());
- s = htmlEntityDecode(s);
- s = xmlEntityEncode(s);
-
- // Fix quotations around font strings and gradient URLs
- s = s.replace(DUMMY_REGEX, '\'');
-
- // IE is very strict, so we will need to clean
- // svg with the following regex
- // yes this is messy, but do not know a better way
- // Even with this IE will not work due to tainted canvas
- // see https://github.com/kangax/fabric.js/issues/1957
- // http://stackoverflow.com/questions/18112047/canvas-todataurl-working-in-all-browsers-except-ie10
- // Leave here just in case the CORS/tainted IE issue gets resolved
- if(Lib.isIE()) {
- // replace double quote with single quote
- s = s.replace(/"/gi, '\'');
- // url in svg are single quoted
- // since we changed double to single
- // we'll need to change these to double-quoted
- s = s.replace(/(\('#)([^']*)('\))/gi, '(\"#$2\")');
- // font names with spaces will be escaped single-quoted
- // we'll need to change these to double-quoted
- s = s.replace(/(\\')/gi, '\"');
- }
-
- return s;
-};
-
-},{"../components/color":51,"../components/drawing":72,"../constants/xmlns_namespaces":150,"../lib":168,"d3":16}],265:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var mergeArray = _dereq_('../../lib').mergeArray;
-
-// arrayOk attributes, merge them into calcdata array
-module.exports = function arraysToCalcdata(cd, trace) {
- for(var i = 0; i < cd.length; i++) cd[i].i = i;
-
- mergeArray(trace.text, cd, 'tx');
- mergeArray(trace.hovertext, cd, 'htx');
-
- var marker = trace.marker;
- if(marker) {
- mergeArray(marker.opacity, cd, 'mo');
- mergeArray(marker.color, cd, 'mc');
-
- var markerLine = marker.line;
- if(markerLine) {
- mergeArray(markerLine.color, cd, 'mlc');
- mergeArray(markerLine.width, cd, 'mlw');
- }
- }
-};
-
-},{"../../lib":168}],266:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var scatterAttrs = _dereq_('../scatter/attributes');
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
-var colorScaleAttrs = _dereq_('../../components/colorscale/attributes');
-var fontAttrs = _dereq_('../../plots/font_attributes');
-var constants = _dereq_('./constants.js');
-
-var extendFlat = _dereq_('../../lib/extend').extendFlat;
-
-var textFontAttrs = fontAttrs({
- editType: 'calc',
- arrayOk: true,
- colorEditType: 'style',
-
-});
-
-var scatterMarkerAttrs = scatterAttrs.marker;
-var scatterMarkerLineAttrs = scatterMarkerAttrs.line;
-
-var markerLineWidth = extendFlat({},
- scatterMarkerLineAttrs.width, { dflt: 0 });
-
-var markerLine = extendFlat({
- width: markerLineWidth,
- editType: 'calc'
-}, colorScaleAttrs('marker.line'));
-
-var marker = extendFlat({
- line: markerLine,
- editType: 'calc'
-}, colorScaleAttrs('marker'), {
- opacity: {
- valType: 'number',
- arrayOk: true,
- dflt: 1,
- min: 0,
- max: 1,
-
- editType: 'style',
-
- }
-});
-
-module.exports = {
- x: scatterAttrs.x,
- x0: scatterAttrs.x0,
- dx: scatterAttrs.dx,
- y: scatterAttrs.y,
- y0: scatterAttrs.y0,
- dy: scatterAttrs.dy,
-
- text: scatterAttrs.text,
- hovertext: scatterAttrs.hovertext,
- hovertemplate: hovertemplateAttrs({}, {
- keys: constants.eventDataKeys
- }),
-
- textposition: {
- valType: 'enumerated',
-
- values: ['inside', 'outside', 'auto', 'none'],
- dflt: 'none',
- arrayOk: true,
- editType: 'calc',
-
- },
-
- insidetextanchor: {
- valType: 'enumerated',
- values: ['end', 'middle', 'start'],
- dflt: 'end',
-
- editType: 'plot',
-
- },
-
- textangle: {
- valType: 'angle',
- dflt: 'auto',
-
- editType: 'plot',
-
- },
-
- textfont: extendFlat({}, textFontAttrs, {
-
- }),
-
- insidetextfont: extendFlat({}, textFontAttrs, {
-
- }),
-
- outsidetextfont: extendFlat({}, textFontAttrs, {
-
- }),
-
- constraintext: {
- valType: 'enumerated',
- values: ['inside', 'outside', 'both', 'none'],
-
- dflt: 'both',
- editType: 'calc',
-
- },
-
- cliponaxis: extendFlat({}, scatterAttrs.cliponaxis, {
-
- }),
-
- orientation: {
- valType: 'enumerated',
-
- values: ['v', 'h'],
- editType: 'calc+clearAxisTypes',
-
- },
-
- base: {
- valType: 'any',
- dflt: null,
- arrayOk: true,
-
- editType: 'calc',
-
- },
-
- offset: {
- valType: 'number',
- dflt: null,
- arrayOk: true,
-
- editType: 'calc',
-
- },
-
- width: {
- valType: 'number',
- dflt: null,
- min: 0,
- arrayOk: true,
-
- editType: 'calc',
-
- },
-
- marker: marker,
-
- offsetgroup: {
- valType: 'string',
-
- dflt: '',
- editType: 'calc',
-
- },
- alignmentgroup: {
- valType: 'string',
-
- dflt: '',
- editType: 'calc',
-
- },
-
- selected: {
- marker: {
- opacity: scatterAttrs.selected.marker.opacity,
- color: scatterAttrs.selected.marker.color,
- editType: 'style'
- },
- textfont: scatterAttrs.selected.textfont,
- editType: 'style'
- },
- unselected: {
- marker: {
- opacity: scatterAttrs.unselected.marker.opacity,
- color: scatterAttrs.unselected.marker.color,
- editType: 'style'
- },
- textfont: scatterAttrs.unselected.textfont,
- editType: 'style'
- },
-
- r: scatterAttrs.r,
- t: scatterAttrs.t,
-
- _deprecated: {
- bardir: {
- valType: 'enumerated',
-
- editType: 'calc',
- values: ['v', 'h'],
-
- }
- }
-};
-
-},{"../../components/colorscale/attributes":58,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../../plots/font_attributes":238,"../scatter/attributes":365,"./constants.js":268}],267:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Axes = _dereq_('../../plots/cartesian/axes');
-var hasColorscale = _dereq_('../../components/colorscale/helpers').hasColorscale;
-var colorscaleCalc = _dereq_('../../components/colorscale/calc');
-var arraysToCalcdata = _dereq_('./arrays_to_calcdata');
-var calcSelection = _dereq_('../scatter/calc_selection');
-
-module.exports = function calc(gd, trace) {
- var xa = Axes.getFromId(gd, trace.xaxis || 'x');
- var ya = Axes.getFromId(gd, trace.yaxis || 'y');
- var size, pos;
-
- if(trace.orientation === 'h') {
- size = xa.makeCalcdata(trace, 'x');
- pos = ya.makeCalcdata(trace, 'y');
- } else {
- size = ya.makeCalcdata(trace, 'y');
- pos = xa.makeCalcdata(trace, 'x');
- }
-
- // create the "calculated data" to plot
- var serieslen = Math.min(pos.length, size.length);
- var cd = new Array(serieslen);
-
- // set position and size
- for(var i = 0; i < serieslen; i++) {
- cd[i] = { p: pos[i], s: size[i] };
-
- if(trace.ids) {
- cd[i].id = String(trace.ids[i]);
- }
- }
-
- // auto-z and autocolorscale if applicable
- if(hasColorscale(trace, 'marker')) {
- colorscaleCalc(gd, trace, {
- vals: trace.marker.color,
- containerStr: 'marker',
- cLetter: 'c'
- });
- }
- if(hasColorscale(trace, 'marker.line')) {
- colorscaleCalc(gd, trace, {
- vals: trace.marker.line.color,
- containerStr: 'marker.line',
- cLetter: 'c'
- });
- }
-
- arraysToCalcdata(cd, trace);
- calcSelection(cd, trace);
-
- return cd;
-};
-
-},{"../../components/colorscale/calc":59,"../../components/colorscale/helpers":62,"../../plots/cartesian/axes":212,"../scatter/calc_selection":367,"./arrays_to_calcdata":265}],268:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-module.exports = {
- eventDataKeys: []
-};
-
-},{}],269:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var isNumeric = _dereq_('fast-isnumeric');
-var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray;
-var BADNUM = _dereq_('../../constants/numerical').BADNUM;
-
-var Registry = _dereq_('../../registry');
-var Axes = _dereq_('../../plots/cartesian/axes');
-var getAxisGroup = _dereq_('../../plots/cartesian/axis_ids').getAxisGroup;
-var Sieve = _dereq_('./sieve.js');
-
-/*
- * Bar chart stacking/grouping positioning and autoscaling calculations
- * for each direction separately calculate the ranges and positions
- * note that this handles histograms too
- * now doing this one subplot at a time
- */
-
-function crossTraceCalc(gd, plotinfo) {
- var xa = plotinfo.xaxis;
- var ya = plotinfo.yaxis;
-
- var fullLayout = gd._fullLayout;
- var fullTraces = gd._fullData;
- var calcTraces = gd.calcdata;
- var calcTracesHorz = [];
- var calcTracesVert = [];
-
- for(var i = 0; i < fullTraces.length; i++) {
- var fullTrace = fullTraces[i];
- if(
- fullTrace.visible === true &&
- Registry.traceIs(fullTrace, 'bar') &&
- fullTrace.xaxis === xa._id &&
- fullTrace.yaxis === ya._id
- ) {
- if(fullTrace.orientation === 'h') {
- calcTracesHorz.push(calcTraces[i]);
- } else {
- calcTracesVert.push(calcTraces[i]);
- }
- }
- }
-
- var opts = {
- mode: fullLayout.barmode,
- norm: fullLayout.barnorm,
- gap: fullLayout.bargap,
- groupgap: fullLayout.bargroupgap
- };
-
- setGroupPositions(gd, xa, ya, calcTracesVert, opts);
- setGroupPositions(gd, ya, xa, calcTracesHorz, opts);
-}
-
-function setGroupPositions(gd, pa, sa, calcTraces, opts) {
- if(!calcTraces.length) return;
-
- var excluded;
- var included;
- var i, calcTrace, fullTrace;
-
- initBase(sa, calcTraces);
-
- switch(opts.mode) {
- case 'overlay':
- setGroupPositionsInOverlayMode(pa, sa, calcTraces, opts);
- break;
-
- case 'group':
- // exclude from the group those traces for which the user set an offset
- excluded = [];
- included = [];
- for(i = 0; i < calcTraces.length; i++) {
- calcTrace = calcTraces[i];
- fullTrace = calcTrace[0].trace;
-
- if(fullTrace.offset === undefined) included.push(calcTrace);
- else excluded.push(calcTrace);
- }
-
- if(included.length) {
- setGroupPositionsInGroupMode(gd, pa, sa, included, opts);
- }
- if(excluded.length) {
- setGroupPositionsInOverlayMode(pa, sa, excluded, opts);
- }
- break;
-
- case 'stack':
- case 'relative':
- // exclude from the stack those traces for which the user set a base
- excluded = [];
- included = [];
- for(i = 0; i < calcTraces.length; i++) {
- calcTrace = calcTraces[i];
- fullTrace = calcTrace[0].trace;
-
- if(fullTrace.base === undefined) included.push(calcTrace);
- else excluded.push(calcTrace);
- }
-
- if(included.length) {
- setGroupPositionsInStackOrRelativeMode(gd, pa, sa, included, opts);
- }
- if(excluded.length) {
- setGroupPositionsInOverlayMode(pa, sa, excluded, opts);
- }
- break;
- }
-
- collectExtents(calcTraces, pa);
-}
-
-function initBase(sa, calcTraces) {
- var i, j;
-
- for(i = 0; i < calcTraces.length; i++) {
- var cd = calcTraces[i];
- var trace = cd[0].trace;
- var base = (trace.type === 'funnel') ? trace._base : trace.base;
- var b;
-
- // not sure if it really makes sense to have dates for bar size data...
- // ideally if we want to make gantt charts or something we'd treat
- // the actual size (trace.x or y) as time delta but base as absolute
- // time. But included here for completeness.
- var scalendar = trace.orientation === 'h' ? trace.xcalendar : trace.ycalendar;
-
- // 'base' on categorical axes makes no sense
- var d2c = sa.type === 'category' || sa.type === 'multicategory' ?
- function() { return null; } :
- sa.d2c;
-
- if(isArrayOrTypedArray(base)) {
- for(j = 0; j < Math.min(base.length, cd.length); j++) {
- b = d2c(base[j], 0, scalendar);
- if(isNumeric(b)) {
- cd[j].b = +b;
- cd[j].hasB = 1;
- } else cd[j].b = 0;
- }
- for(; j < cd.length; j++) {
- cd[j].b = 0;
- }
- } else {
- b = d2c(base, 0, scalendar);
- var hasBase = isNumeric(b);
- b = hasBase ? b : 0;
- for(j = 0; j < cd.length; j++) {
- cd[j].b = b;
- if(hasBase) cd[j].hasB = 1;
- }
- }
- }
-}
-
-function setGroupPositionsInOverlayMode(pa, sa, calcTraces, opts) {
- // update position axis and set bar offsets and widths
- for(var i = 0; i < calcTraces.length; i++) {
- var calcTrace = calcTraces[i];
-
- var sieve = new Sieve([calcTrace], {
- sepNegVal: false,
- overlapNoMerge: !opts.norm
- });
-
- // set bar offsets and widths, and update position axis
- setOffsetAndWidth(pa, sieve, opts);
-
- // set bar bases and sizes, and update size axis
- //
- // (note that `setGroupPositionsInOverlayMode` handles the case barnorm
- // is defined, because this function is also invoked for traces that
- // can't be grouped or stacked)
- if(opts.norm) {
- sieveBars(sieve);
- normalizeBars(sa, sieve, opts);
- } else {
- setBaseAndTop(sa, sieve);
- }
- }
-}
-
-function setGroupPositionsInGroupMode(gd, pa, sa, calcTraces, opts) {
- var sieve = new Sieve(calcTraces, {
- sepNegVal: false,
- overlapNoMerge: !opts.norm
- });
-
- // set bar offsets and widths, and update position axis
- setOffsetAndWidthInGroupMode(gd, pa, sieve, opts);
-
- // relative-stack bars within the same trace that would otherwise
- // be hidden
- unhideBarsWithinTrace(sieve);
-
- // set bar bases and sizes, and update size axis
- if(opts.norm) {
- sieveBars(sieve);
- normalizeBars(sa, sieve, opts);
- } else {
- setBaseAndTop(sa, sieve);
- }
-}
-
-function setGroupPositionsInStackOrRelativeMode(gd, pa, sa, calcTraces, opts) {
- var sieve = new Sieve(calcTraces, {
- sepNegVal: opts.mode === 'relative',
- overlapNoMerge: !(opts.norm || opts.mode === 'stack' || opts.mode === 'relative')
- });
-
- // set bar offsets and widths, and update position axis
- setOffsetAndWidth(pa, sieve, opts);
-
- // set bar bases and sizes, and update size axis
- stackBars(sa, sieve, opts);
-
- // flag the outmost bar (for text display purposes)
- for(var i = 0; i < calcTraces.length; i++) {
- var calcTrace = calcTraces[i];
-
- for(var j = 0; j < calcTrace.length; j++) {
- var bar = calcTrace[j];
-
- if(bar.s !== BADNUM) {
- var isOutmostBar = ((bar.b + bar.s) === sieve.get(bar.p, bar.s));
- if(isOutmostBar) bar._outmost = true;
- }
- }
- }
-
- // Note that marking the outmost bars has to be done
- // before `normalizeBars` changes `bar.b` and `bar.s`.
- if(opts.norm) normalizeBars(sa, sieve, opts);
-}
-
-function setOffsetAndWidth(pa, sieve, opts) {
- var minDiff = sieve.minDiff;
- var calcTraces = sieve.traces;
-
- // set bar offsets and widths
- var barGroupWidth = minDiff * (1 - opts.gap);
- var barWidthPlusGap = barGroupWidth;
- var barWidth = barWidthPlusGap * (1 - (opts.groupgap || 0));
-
- // computer bar group center and bar offset
- var offsetFromCenter = -barWidth / 2;
-
- for(var i = 0; i < calcTraces.length; i++) {
- var calcTrace = calcTraces[i];
- var t = calcTrace[0].t;
-
- // store bar width and offset for this trace
- t.barwidth = barWidth;
- t.poffset = offsetFromCenter;
- t.bargroupwidth = barGroupWidth;
- t.bardelta = minDiff;
- }
-
- // stack bars that only differ by rounding
- sieve.binWidth = calcTraces[0][0].t.barwidth / 100;
-
- // if defined, apply trace offset and width
- applyAttributes(sieve);
-
- // store the bar center in each calcdata item
- setBarCenterAndWidth(pa, sieve);
-
- // update position axes
- updatePositionAxis(pa, sieve);
-}
-
-function setOffsetAndWidthInGroupMode(gd, pa, sieve, opts) {
- var fullLayout = gd._fullLayout;
- var positions = sieve.positions;
- var distinctPositions = sieve.distinctPositions;
- var minDiff = sieve.minDiff;
- var calcTraces = sieve.traces;
- var nTraces = calcTraces.length;
-
- // if there aren't any overlapping positions,
- // let them have full width even if mode is group
- var overlap = (positions.length !== distinctPositions.length);
- var barGroupWidth = minDiff * (1 - opts.gap);
-
- var groupId = getAxisGroup(fullLayout, pa._id) + calcTraces[0][0].trace.orientation;
- var alignmentGroups = fullLayout._alignmentOpts[groupId] || {};
-
- for(var i = 0; i < nTraces; i++) {
- var calcTrace = calcTraces[i];
- var trace = calcTrace[0].trace;
-
- var alignmentGroupOpts = alignmentGroups[trace.alignmentgroup] || {};
- var nOffsetGroups = Object.keys(alignmentGroupOpts.offsetGroups || {}).length;
-
- var barWidthPlusGap;
- if(nOffsetGroups) {
- barWidthPlusGap = barGroupWidth / nOffsetGroups;
- } else {
- barWidthPlusGap = overlap ? barGroupWidth / nTraces : barGroupWidth;
- }
-
- var barWidth = barWidthPlusGap * (1 - (opts.groupgap || 0));
-
- var offsetFromCenter;
- if(nOffsetGroups) {
- offsetFromCenter = ((2 * trace._offsetIndex + 1 - nOffsetGroups) * barWidthPlusGap - barWidth) / 2;
- } else {
- offsetFromCenter = overlap ?
- ((2 * i + 1 - nTraces) * barWidthPlusGap - barWidth) / 2 :
- -barWidth / 2;
- }
-
- var t = calcTrace[0].t;
- t.barwidth = barWidth;
- t.poffset = offsetFromCenter;
- t.bargroupwidth = barGroupWidth;
- t.bardelta = minDiff;
- }
-
- // stack bars that only differ by rounding
- sieve.binWidth = calcTraces[0][0].t.barwidth / 100;
-
- // if defined, apply trace width
- applyAttributes(sieve);
-
- // store the bar center in each calcdata item
- setBarCenterAndWidth(pa, sieve);
-
- // update position axes
- updatePositionAxis(pa, sieve, overlap);
-}
-
-function applyAttributes(sieve) {
- var calcTraces = sieve.traces;
- var i, j;
-
- for(i = 0; i < calcTraces.length; i++) {
- var calcTrace = calcTraces[i];
- var calcTrace0 = calcTrace[0];
- var fullTrace = calcTrace0.trace;
- var t = calcTrace0.t;
- var offset = fullTrace._offset || fullTrace.offset;
- var initialPoffset = t.poffset;
- var newPoffset;
-
- if(isArrayOrTypedArray(offset)) {
- // if offset is an array, then clone it into t.poffset.
- newPoffset = Array.prototype.slice.call(offset, 0, calcTrace.length);
-
- // guard against non-numeric items
- for(j = 0; j < newPoffset.length; j++) {
- if(!isNumeric(newPoffset[j])) {
- newPoffset[j] = initialPoffset;
- }
- }
-
- // if the length of the array is too short,
- // then extend it with the initial value of t.poffset
- for(j = newPoffset.length; j < calcTrace.length; j++) {
- newPoffset.push(initialPoffset);
- }
-
- t.poffset = newPoffset;
- } else if(offset !== undefined) {
- t.poffset = offset;
- }
-
- var width = fullTrace._width || fullTrace.width;
- var initialBarwidth = t.barwidth;
-
- if(isArrayOrTypedArray(width)) {
- // if width is an array, then clone it into t.barwidth.
- var newBarwidth = Array.prototype.slice.call(width, 0, calcTrace.length);
-
- // guard against non-numeric items
- for(j = 0; j < newBarwidth.length; j++) {
- if(!isNumeric(newBarwidth[j])) newBarwidth[j] = initialBarwidth;
- }
-
- // if the length of the array is too short,
- // then extend it with the initial value of t.barwidth
- for(j = newBarwidth.length; j < calcTrace.length; j++) {
- newBarwidth.push(initialBarwidth);
- }
-
- t.barwidth = newBarwidth;
-
- // if user didn't set offset,
- // then correct t.poffset to ensure bars remain centered
- if(offset === undefined) {
- newPoffset = [];
- for(j = 0; j < calcTrace.length; j++) {
- newPoffset.push(
- initialPoffset + (initialBarwidth - newBarwidth[j]) / 2
- );
- }
- t.poffset = newPoffset;
- }
- } else if(width !== undefined) {
- t.barwidth = width;
-
- // if user didn't set offset,
- // then correct t.poffset to ensure bars remain centered
- if(offset === undefined) {
- t.poffset = initialPoffset + (initialBarwidth - width) / 2;
- }
- }
- }
-}
-
-function setBarCenterAndWidth(pa, sieve) {
- var calcTraces = sieve.traces;
- var pLetter = getAxisLetter(pa);
-
- for(var i = 0; i < calcTraces.length; i++) {
- var calcTrace = calcTraces[i];
- var t = calcTrace[0].t;
- var poffset = t.poffset;
- var poffsetIsArray = Array.isArray(poffset);
- var barwidth = t.barwidth;
- var barwidthIsArray = Array.isArray(barwidth);
-
- for(var j = 0; j < calcTrace.length; j++) {
- var calcBar = calcTrace[j];
-
- // store the actual bar width and position, for use by hover
- var width = calcBar.w = barwidthIsArray ? barwidth[j] : barwidth;
- calcBar[pLetter] = calcBar.p + (poffsetIsArray ? poffset[j] : poffset) + width / 2;
- }
- }
-}
-
-function updatePositionAxis(pa, sieve, allowMinDtick) {
- var calcTraces = sieve.traces;
- var minDiff = sieve.minDiff;
- var vpad = minDiff / 2;
-
- Axes.minDtick(pa, sieve.minDiff, sieve.distinctPositions[0], allowMinDtick);
-
- for(var i = 0; i < calcTraces.length; i++) {
- var calcTrace = calcTraces[i];
- var calcTrace0 = calcTrace[0];
- var fullTrace = calcTrace0.trace;
- var pts = [];
- var bar, l, r, j;
-
- for(j = 0; j < calcTrace.length; j++) {
- bar = calcTrace[j];
- l = bar.p - vpad;
- r = bar.p + vpad;
- pts.push(l, r);
- }
-
- if(fullTrace.width || fullTrace.offset) {
- var t = calcTrace0.t;
- var poffset = t.poffset;
- var barwidth = t.barwidth;
- var poffsetIsArray = Array.isArray(poffset);
- var barwidthIsArray = Array.isArray(barwidth);
-
- for(j = 0; j < calcTrace.length; j++) {
- bar = calcTrace[j];
- var calcBarOffset = poffsetIsArray ? poffset[j] : poffset;
- var calcBarWidth = barwidthIsArray ? barwidth[j] : barwidth;
- l = bar.p + calcBarOffset;
- r = l + calcBarWidth;
- pts.push(l, r);
- }
- }
-
- fullTrace._extremes[pa._id] = Axes.findExtremes(pa, pts, {padded: false});
- }
-}
-
-// store these bar bases and tops in calcdata
-// and make sure the size axis includes zero,
-// along with the bases and tops of each bar.
-function setBaseAndTop(sa, sieve) {
- var calcTraces = sieve.traces;
- var sLetter = getAxisLetter(sa);
-
- for(var i = 0; i < calcTraces.length; i++) {
- var calcTrace = calcTraces[i];
- var fullTrace = calcTrace[0].trace;
- var pts = [];
- var allBaseAboveZero = true;
-
- for(var j = 0; j < calcTrace.length; j++) {
- var bar = calcTrace[j];
- var base = bar.b;
- var top = base + bar.s;
-
- bar[sLetter] = top;
- pts.push(top);
- if(bar.hasB) pts.push(base);
-
- if(!bar.hasB || !(bar.b > 0 && bar.s > 0)) {
- allBaseAboveZero = false;
- }
- }
-
- fullTrace._extremes[sa._id] = Axes.findExtremes(sa, pts, {
- tozero: !allBaseAboveZero,
- padded: true
- });
- }
-}
-
-function stackBars(sa, sieve, opts) {
- var sLetter = getAxisLetter(sa);
- var calcTraces = sieve.traces;
- var calcTrace;
- var fullTrace;
- var isFunnel;
- var i, j;
- var bar;
-
- for(i = 0; i < calcTraces.length; i++) {
- calcTrace = calcTraces[i];
- fullTrace = calcTrace[0].trace;
-
- if(fullTrace.type === 'funnel') {
- for(j = 0; j < calcTrace.length; j++) {
- bar = calcTrace[j];
-
- if(bar.s !== BADNUM) {
- // create base of funnels
- sieve.put(bar.p, -0.5 * bar.s);
- }
- }
- }
- }
-
- for(i = 0; i < calcTraces.length; i++) {
- calcTrace = calcTraces[i];
- fullTrace = calcTrace[0].trace;
-
- isFunnel = (fullTrace.type === 'funnel');
-
- var pts = [];
-
- for(j = 0; j < calcTrace.length; j++) {
- bar = calcTrace[j];
-
- if(bar.s !== BADNUM) {
- // stack current bar and get previous sum
- var value;
- if(isFunnel) {
- value = bar.s;
- } else {
- value = bar.s + bar.b;
- }
-
- var base = sieve.put(bar.p, value);
-
- var top = base + value;
-
- // store the bar base and top in each calcdata item
- bar.b = base;
- bar[sLetter] = top;
-
- if(!opts.norm) {
- pts.push(top);
- if(bar.hasB) {
- pts.push(base);
- }
- }
- }
- }
-
- // if barnorm is set, let normalizeBars update the axis range
- if(!opts.norm) {
- fullTrace._extremes[sa._id] = Axes.findExtremes(sa, pts, {
- // N.B. we don't stack base with 'base',
- // so set tozero:true always!
- tozero: true,
- padded: true
- });
- }
- }
-}
-
-function sieveBars(sieve) {
- var calcTraces = sieve.traces;
-
- for(var i = 0; i < calcTraces.length; i++) {
- var calcTrace = calcTraces[i];
-
- for(var j = 0; j < calcTrace.length; j++) {
- var bar = calcTrace[j];
-
- if(bar.s !== BADNUM) {
- sieve.put(bar.p, bar.b + bar.s);
- }
- }
- }
-}
-
-function unhideBarsWithinTrace(sieve) {
- var calcTraces = sieve.traces;
-
- for(var i = 0; i < calcTraces.length; i++) {
- var calcTrace = calcTraces[i];
- var fullTrace = calcTrace[0].trace;
-
- if(fullTrace.base === undefined) {
- var inTraceSieve = new Sieve([calcTrace], {
- sepNegVal: true,
- overlapNoMerge: true
- });
-
- for(var j = 0; j < calcTrace.length; j++) {
- var bar = calcTrace[j];
-
- if(bar.p !== BADNUM) {
- // stack current bar and get previous sum
- var base = inTraceSieve.put(bar.p, bar.b + bar.s);
-
- // if previous sum if non-zero, this means:
- // multiple bars have same starting point are potentially hidden,
- // shift them vertically so that all bars are visible by default
- if(base) bar.b = base;
- }
- }
- }
- }
-}
-
-// Note:
-//
-// normalizeBars requires that either sieveBars or stackBars has been
-// previously invoked.
-function normalizeBars(sa, sieve, opts) {
- var calcTraces = sieve.traces;
- var sLetter = getAxisLetter(sa);
- var sTop = opts.norm === 'fraction' ? 1 : 100;
- var sTiny = sTop / 1e9; // in case of rounding error in sum
- var sMin = sa.l2c(sa.c2l(0));
- var sMax = opts.mode === 'stack' ? sTop : sMin;
-
- function needsPadding(v) {
- return (
- isNumeric(sa.c2l(v)) &&
- ((v < sMin - sTiny) || (v > sMax + sTiny) || !isNumeric(sMin))
- );
- }
-
- for(var i = 0; i < calcTraces.length; i++) {
- var calcTrace = calcTraces[i];
- var fullTrace = calcTrace[0].trace;
- var pts = [];
- var allBaseAboveZero = true;
- var padded = false;
-
- for(var j = 0; j < calcTrace.length; j++) {
- var bar = calcTrace[j];
-
- if(bar.s !== BADNUM) {
- var scale = Math.abs(sTop / sieve.get(bar.p, bar.s));
- bar.b *= scale;
- bar.s *= scale;
-
- var base = bar.b;
- var top = base + bar.s;
-
- bar[sLetter] = top;
- pts.push(top);
- padded = padded || needsPadding(top);
-
- if(bar.hasB) {
- pts.push(base);
- padded = padded || needsPadding(base);
- }
-
- if(!bar.hasB || !(bar.b > 0 && bar.s > 0)) {
- allBaseAboveZero = false;
- }
- }
- }
-
- fullTrace._extremes[sa._id] = Axes.findExtremes(sa, pts, {
- tozero: !allBaseAboveZero,
- padded: padded
- });
- }
-}
-
-// find the full position span of bars at each position
-// for use by hover, to ensure labels move in if bars are
-// narrower than the space they're in.
-// run once per trace group (subplot & direction) and
-// the same mapping is attached to all calcdata traces
-function collectExtents(calcTraces, pa) {
- var pLetter = getAxisLetter(pa);
- var extents = {};
- var i, j, cd;
-
- var pMin = Infinity;
- var pMax = -Infinity;
-
- for(i = 0; i < calcTraces.length; i++) {
- cd = calcTraces[i];
- for(j = 0; j < cd.length; j++) {
- var p = cd[j].p;
- if(isNumeric(p)) {
- pMin = Math.min(pMin, p);
- pMax = Math.max(pMax, p);
- }
- }
- }
-
- // this is just for positioning of hover labels, and nobody will care if
- // the label is 1px too far out; so round positions to 1/10K in case
- // position values don't exactly match from trace to trace
- var roundFactor = 10000 / (pMax - pMin);
- var round = extents.round = function(p) {
- return String(Math.round(roundFactor * (p - pMin)));
- };
-
- for(i = 0; i < calcTraces.length; i++) {
- cd = calcTraces[i];
- cd[0].t.extents = extents;
-
- var poffset = cd[0].t.poffset;
- var poffsetIsArray = Array.isArray(poffset);
-
- for(j = 0; j < cd.length; j++) {
- var di = cd[j];
- var p0 = di[pLetter] - di.w / 2;
-
- if(isNumeric(p0)) {
- var p1 = di[pLetter] + di.w / 2;
- var pVal = round(di.p);
- if(extents[pVal]) {
- extents[pVal] = [Math.min(p0, extents[pVal][0]), Math.max(p1, extents[pVal][1])];
- } else {
- extents[pVal] = [p0, p1];
- }
- }
-
- di.p0 = di.p + (poffsetIsArray ? poffset[j] : poffset);
- di.p1 = di.p0 + di.w;
- di.s0 = di.b;
- di.s1 = di.s0 + di.s;
- }
- }
-}
-
-function getAxisLetter(ax) {
- return ax._id.charAt(0);
-}
-
-module.exports = {
- crossTraceCalc: crossTraceCalc,
- setGroupPositions: setGroupPositions
-};
-
-},{"../../constants/numerical":149,"../../lib":168,"../../plots/cartesian/axes":212,"../../plots/cartesian/axis_ids":215,"../../registry":256,"./sieve.js":278,"fast-isnumeric":18}],270:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var Color = _dereq_('../../components/color');
-var Registry = _dereq_('../../registry');
-
-var handleXYDefaults = _dereq_('../scatter/xy_defaults');
-var handleStyleDefaults = _dereq_('./style_defaults');
-var getAxisGroup = _dereq_('../../plots/cartesian/axis_ids').getAxisGroup;
-var attributes = _dereq_('./attributes');
-
-var coerceFont = Lib.coerceFont;
-
-function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
- function coerce(attr, dflt) {
- return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
- }
-
- var len = handleXYDefaults(traceIn, traceOut, layout, coerce);
- if(!len) {
- traceOut.visible = false;
- return;
- }
-
- coerce('orientation', (traceOut.x && !traceOut.y) ? 'h' : 'v');
- coerce('base');
- coerce('offset');
- coerce('width');
-
- coerce('text');
- coerce('hovertext');
- coerce('hovertemplate');
-
- var textposition = coerce('textposition');
- handleText(traceIn, traceOut, layout, coerce, textposition, {
- moduleHasSelected: true,
- moduleHasUnselected: true,
- moduleHasConstrain: true,
- moduleHasCliponaxis: true,
- moduleHasTextangle: true,
- moduleHasInsideanchor: true
- });
-
- handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout);
-
- var lineColor = (traceOut.marker.line || {}).color;
-
- // override defaultColor for error bars with defaultLine
- var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults');
- errorBarsSupplyDefaults(traceIn, traceOut, lineColor || Color.defaultLine, {axis: 'y'});
- errorBarsSupplyDefaults(traceIn, traceOut, lineColor || Color.defaultLine, {axis: 'x', inherit: 'y'});
-
- Lib.coerceSelectionMarkerOpacity(traceOut, coerce);
-}
-
-function handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce) {
- var orientation = traceOut.orientation;
- // N.B. grouping is done across all trace types that support it
- var posAxId = traceOut[{v: 'x', h: 'y'}[orientation] + 'axis'];
- var groupId = getAxisGroup(fullLayout, posAxId) + orientation;
-
- var alignmentOpts = fullLayout._alignmentOpts || {};
- var alignmentgroup = coerce('alignmentgroup');
-
- var alignmentGroups = alignmentOpts[groupId];
- if(!alignmentGroups) alignmentGroups = alignmentOpts[groupId] = {};
-
- var alignmentGroupOpts = alignmentGroups[alignmentgroup];
-
- if(alignmentGroupOpts) {
- alignmentGroupOpts.traces.push(traceOut);
- } else {
- alignmentGroupOpts = alignmentGroups[alignmentgroup] = {
- traces: [traceOut],
- alignmentIndex: Object.keys(alignmentGroups).length,
- offsetGroups: {}
- };
- }
-
- var offsetgroup = coerce('offsetgroup');
- var offsetGroups = alignmentGroupOpts.offsetGroups;
- var offsetGroupOpts = offsetGroups[offsetgroup];
-
- if(offsetgroup) {
- if(!offsetGroupOpts) {
- offsetGroupOpts = offsetGroups[offsetgroup] = {
- offsetIndex: Object.keys(offsetGroups).length
- };
- }
-
- traceOut._offsetIndex = offsetGroupOpts.offsetIndex;
- }
-}
-
-function crossTraceDefaults(fullData, fullLayout) {
- var traceIn, traceOut;
-
- function coerce(attr) {
- return Lib.coerce(traceOut._input, traceOut, attributes, attr);
- }
-
- if(fullLayout.barmode === 'group') {
- for(var i = 0; i < fullData.length; i++) {
- traceOut = fullData[i];
-
- if(traceOut.type === 'bar') {
- traceIn = traceOut._input;
- handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce);
- }
- }
- }
-}
-
-function handleText(traceIn, traceOut, layout, coerce, textposition, opts) {
- opts = opts || {};
- var moduleHasSelected = !(opts.moduleHasSelected === false);
- var moduleHasUnselected = !(opts.moduleHasUnselected === false);
- var moduleHasConstrain = !(opts.moduleHasConstrain === false);
- var moduleHasCliponaxis = !(opts.moduleHasCliponaxis === false);
- var moduleHasTextangle = !(opts.moduleHasTextangle === false);
- var moduleHasInsideanchor = !(opts.moduleHasInsideanchor === false);
-
- var hasBoth = Array.isArray(textposition) || textposition === 'auto';
- var hasInside = hasBoth || textposition === 'inside';
- var hasOutside = hasBoth || textposition === 'outside';
-
- if(hasInside || hasOutside) {
- var dfltFont = coerceFont(coerce, 'textfont', layout.font);
-
- // Note that coercing `insidetextfont` is always needed –
- // even if `textposition` is `outside` for each trace – since
- // an outside label can become an inside one, for example because
- // of a bar being stacked on top of it.
- var insideTextFontDefault = Lib.extendFlat({}, dfltFont);
- var isTraceTextfontColorSet = traceIn.textfont && traceIn.textfont.color;
- var isColorInheritedFromLayoutFont = !isTraceTextfontColorSet;
- if(isColorInheritedFromLayoutFont) {
- delete insideTextFontDefault.color;
- }
- coerceFont(coerce, 'insidetextfont', insideTextFontDefault);
-
- if(hasOutside) coerceFont(coerce, 'outsidetextfont', dfltFont);
-
-
- if(moduleHasSelected) coerce('selected.textfont.color');
- if(moduleHasUnselected) coerce('unselected.textfont.color');
- if(moduleHasConstrain) coerce('constraintext');
- if(moduleHasCliponaxis) coerce('cliponaxis');
- if(moduleHasTextangle) coerce('textangle');
- }
-
- if(hasInside) {
- if(moduleHasInsideanchor) coerce('insidetextanchor');
- }
-}
-
-module.exports = {
- supplyDefaults: supplyDefaults,
- crossTraceDefaults: crossTraceDefaults,
- handleGroupingDefaults: handleGroupingDefaults,
- handleText: handleText
-};
-
-},{"../../components/color":51,"../../lib":168,"../../plots/cartesian/axis_ids":215,"../../registry":256,"../scatter/xy_defaults":390,"./attributes":266,"./style_defaults":280}],271:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var isNumeric = _dereq_('fast-isnumeric');
-var tinycolor = _dereq_('tinycolor2');
-
-exports.coerceString = function(attributeDefinition, value, defaultValue) {
- if(typeof value === 'string') {
- if(value || !attributeDefinition.noBlank) return value;
- } else if(typeof value === 'number' || value === true) {
- if(!attributeDefinition.strict) return String(value);
- }
-
- return (defaultValue !== undefined) ?
- defaultValue :
- attributeDefinition.dflt;
-};
-
-exports.coerceNumber = function(attributeDefinition, value, defaultValue) {
- if(isNumeric(value)) {
- value = +value;
-
- var min = attributeDefinition.min;
- var max = attributeDefinition.max;
- var isOutOfBounds = (min !== undefined && value < min) ||
- (max !== undefined && value > max);
-
- 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(index < arrayOrScalar.length) value = arrayOrScalar[index];
- return value;
-};
-
-},{"fast-isnumeric":18,"tinycolor2":34}],272:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var Fx = _dereq_('../../components/fx');
-var Registry = _dereq_('../../registry');
-var Color = _dereq_('../../components/color');
-
-var fillText = _dereq_('../../lib').fillText;
-
-function hoverPoints(pointData, xval, yval, hovermode) {
- var barPointData = hoverOnBars(pointData, xval, yval, hovermode);
-
- if(barPointData) {
- var cd = barPointData.cd;
- var trace = cd[0].trace;
- var di = cd[barPointData.index];
-
- barPointData.color = getTraceColor(trace, di);
- Registry.getComponentMethod('errorbars', 'hoverInfo')(di, trace, barPointData);
-
- return [barPointData];
- }
-}
-
-function hoverOnBars(pointData, xval, yval, hovermode) {
- var cd = pointData.cd;
- var trace = cd[0].trace;
- var t = cd[0].t;
- var isClosest = (hovermode === 'closest');
- var isWaterfall = (trace.type === 'waterfall');
- var maxHoverDistance = pointData.maxHoverDistance;
- var maxSpikeDistance = pointData.maxSpikeDistance;
-
- var posVal, sizeVal, posLetter, sizeLetter, dx, dy, pRangeCalc;
-
- function thisBarMinPos(di) { return di[posLetter] - di.w / 2; }
- function thisBarMaxPos(di) { return di[posLetter] + di.w / 2; }
-
- var minPos = isClosest ?
- thisBarMinPos :
- function(di) {
- /*
- * In compare mode, accept a bar if you're on it *or* its group.
- * Nearly always it's the group that matters, but in case the bar
- * was explicitly set wider than its group we'd better accept the
- * whole bar.
- *
- * use `bardelta` instead of `bargroupwidth` so we accept hover
- * in the gap. That way hover doesn't flash on and off as you
- * mouse over the plot in compare modes.
- * In 'closest' mode though the flashing seems inevitable,
- * without far more complex logic
- */
- return Math.min(thisBarMinPos(di), di.p - t.bardelta / 2);
- };
-
- var maxPos = isClosest ?
- thisBarMaxPos :
- function(di) {
- return Math.max(thisBarMaxPos(di), di.p + t.bardelta / 2);
- };
-
- function _positionFn(_minPos, _maxPos) {
- // add a little to the pseudo-distance for wider bars, so that like scatter,
- // if you are over two overlapping bars, the narrower one wins.
- return Fx.inbox(_minPos - posVal, _maxPos - posVal,
- maxHoverDistance + Math.min(1, Math.abs(_maxPos - _minPos) / pRangeCalc) - 1);
- }
-
- function positionFn(di) {
- return _positionFn(minPos(di), maxPos(di));
- }
-
- function thisBarPositionFn(di) {
- return _positionFn(thisBarMinPos(di), thisBarMaxPos(di));
- }
-
- function sizeFn(di) {
- var v = sizeVal;
- var b = di.b;
- var s = di[sizeLetter];
-
- if(isWaterfall) {
- s += Math.abs(di.rawS || 0);
- }
-
- // add a gradient so hovering near the end of a
- // bar makes it a little closer match
- return 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
- if(pointData.index === false) return;
-
- // if we get here and we're not in 'closest' mode, push min/max pos back
- // onto the group - even though that means occasionally the mouse will be
- // over the hover label.
- if(!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
- var 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;
-
- // spikelines always want "closest" distance regardless of hovermode
- pointData.spikeDistance = (sizeFn(di) + thisBarPositionFn(di)) / 2 + maxSpikeDistance - maxHoverDistance;
- // they also want to point to the data value, regardless of where the label goes
- // in case of bars shifted within groups
- pointData[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 = di.mlw || trace.marker.line.width;
-
- if(Color.opacity(mc)) return mc;
- else if(Color.opacity(mlc) && mlw) return mlc;
-}
-
-module.exports = {
- hoverPoints: hoverPoints,
- hoverOnBars: hoverOnBars,
- getTraceColor: getTraceColor
-};
-
-},{"../../components/color":51,"../../components/fx":90,"../../lib":168,"../../registry":256}],273:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'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,
- selectPoints: _dereq_('./select'),
-
- moduleType: 'trace',
- name: 'bar',
- basePlotModule: _dereq_('../../plots/cartesian'),
- categories: ['bar-like', 'cartesian', 'svg', 'bar', 'oriented', 'errorBarsOK', 'showLegend', 'zoomScale'],
- meta: {
-
- }
-};
-
-},{"../../plots/cartesian":223,"../scatter/marker_colorbar":382,"./arrays_to_calcdata":265,"./attributes":266,"./calc":267,"./cross_trace_calc":269,"./defaults":270,"./hover":272,"./layout_attributes":274,"./layout_defaults":275,"./plot":276,"./select":277,"./style":279}],274:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'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',
-
- }
-};
-
-},{}],275:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'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; i < fullData.length; i++) {
- var trace = fullData[i];
- if(Registry.traceIs(trace, 'bar') && trace.visible) hasBars = true;
- else continue;
-
- // if we have at least 2 grouped bar traces on the same subplot,
- // we should default to a gap anyway, even if the data is histograms
- if(mode === 'group') {
- var subploti = trace.xaxis + trace.yaxis;
- if(usedSubplots[subploti]) gappedAnyway = true;
- usedSubplots[subploti] = true;
- }
-
- if(trace.visible && trace.type === 'histogram') {
- var pa = Axes.getFromId({_fullLayout: layoutOut},
- trace[trace.orientation === 'v' ? 'xaxis' : 'yaxis']);
- if(pa.type !== 'category') shouldBeGapless = true;
- }
- }
-
- if(!hasBars) {
- delete layoutOut.barmode;
- return;
- }
-
- if(mode !== 'overlay') coerce('barnorm');
-
- coerce('bargap', (shouldBeGapless && !gappedAnyway) ? 0 : 0.2);
- coerce('bargroupgap');
-};
-
-},{"../../lib":168,"../../plots/cartesian/axes":212,"../../registry":256,"./layout_attributes":274}],276:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var d3 = _dereq_('d3');
-var isNumeric = _dereq_('fast-isnumeric');
-
-var Lib = _dereq_('../../lib');
-var svgTextUtils = _dereq_('../../lib/svg_text_utils');
-
-var Color = _dereq_('../../components/color');
-var Drawing = _dereq_('../../components/drawing');
-var Registry = _dereq_('../../registry');
-var tickText = _dereq_('../../plots/cartesian/axes').tickText;
-
-var style = _dereq_('./style');
-var helpers = _dereq_('./helpers');
-var attributes = _dereq_('./attributes');
-
-var attributeText = attributes.text;
-var attributeTextPosition = attributes.textposition;
-
-// padding in pixels around text
-var TEXTPAD = 3;
-
-function dirSign(a, b) {
- return (a < b) ? 1 : -1;
-}
-
-function getXY(di, xa, ya, isHorizontal) {
- var s = [];
- var p = [];
-
- var sAxis = isHorizontal ? xa : ya;
- var pAxis = isHorizontal ? ya : xa;
-
- s[0] = sAxis.c2p(di.s0, true);
- p[0] = pAxis.c2p(di.p0, true);
-
- s[1] = sAxis.c2p(di.s1, true);
- p[1] = pAxis.c2p(di.p1, true);
-
- return isHorizontal ? [s, p] : [p, s];
-}
-
-function plot(gd, plotinfo, cdModule, traceLayer, opts) {
- 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
- };
- }
-
- 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');
-
- if(!plotinfo.isRangePlot) cd[0].node3 = plotGroup;
-
- var pointGroup = Lib.ensureSingle(plotGroup, 'g', 'points');
-
- var bars = pointGroup.selectAll('g.point').data(Lib.identity);
-
- bars.enter().append('g')
- .classed('point', true);
-
- bars.exit().remove();
-
- bars.each(function(di, i) {
- var bar = d3.select(this);
-
- // now display the bar
- // clipped xf/yf (2nd arg true): non-positive
- // log values go off-screen by plotwidth
- // so you see them continue if you drag the plot
-
- var 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];
-
- var isBlank = di.isBlank = !(
- isNumeric(x0) && isNumeric(x1) &&
- isNumeric(y0) && isNumeric(y1) &&
- (x0 !== x1 || (shouldDisplayZeros && isHorizontal)) &&
- (y0 !== y1 || (shouldDisplayZeros && !isHorizontal))
- );
-
- // in waterfall mode `between` we need to adjust bar end points to match the connector width
- if(adjustPixel) {
- 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 = (di.mlw + 1 || trace.marker.line.width + 1 ||
- (di.trace ? di.trace.marker.line.width : 0) + 1) - 1;
- mc = di.mc || trace.marker.color;
- }
-
- var offset = d3.round((lw / 2) % 1, 2);
-
- function roundWithLine(v) {
- // if there are explicit gaps, don't round,
- // it can make the gaps look crappy
- return (opts.gap === 0 && opts.groupgap === 0) ?
- d3.round(Math.round(v) - offset, 2) : v;
- }
-
- function expandToVisible(v, vc) {
- // if it's not in danger of disappearing entirely,
- // round more precisely
- return Math.abs(v - vc) >= 2 ? roundWithLine(v) :
- // but if it's very thin, expand it so it's
- // necessarily visible, even if it might overlap
- // its neighbor
- (v > vc ? Math.ceil(v) : Math.floor(v));
- }
-
- if(!gd._context.staticPlot) {
- // if bars are not fully opaque or they have a line
- // around them, round to integer pixels, mainly for
- // safari so we prevent overlaps from its expansive
- // pixelation. if the bars ARE fully opaque and have
- // no line, expand to a full pixel to make sure we
- // can see them
-
- var op = Color.opacity(mc);
- var fixpx = (op < 1 || lw > 0.01) ? roundWithLine : expandToVisible;
- x0 = fixpx(x0, x1);
- x1 = fixpx(x1, x0);
- y0 = fixpx(y0, y1);
- y1 = fixpx(y1, y0);
- }
-
- Lib.ensureSingle(bar, 'path')
- .style('vector-effect', 'non-scaling-stroke')
- .attr('d', isBlank ? 'M0,0Z' : 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z')
- .call(Drawing.setClipUrl, plotinfo.layerClipId, gd);
-
- appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, opts);
-
- if(plotinfo.layerClipId) {
- Drawing.hideOutsideRangePoint(di, bar.select('text'), xa, ya, trace.xcalendar, trace.ycalendar);
- }
- });
-
- // lastly, clip points groups of `cliponaxis !== false` traces
- // on `plotinfo._hasClipOnAxisFalse === true` subplots
- var hasClipOnAxisFalse = trace.cliponaxis === false;
- Drawing.setClipUrl(plotGroup, hasClipOnAxisFalse ? null : plotinfo.layerClipId, gd);
- });
-
- // error bars are on the top
- Registry.getComponentMethod('errorbars', 'plot')(gd, bartraces, plotinfo);
-}
-
-function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts) {
- var xa = plotinfo.xaxis;
- var ya = plotinfo.yaxis;
-
- var fullLayout = gd._fullLayout;
- var textPosition;
-
- function appendTextNode(bar, text, textFont) {
- var textSelection = Lib.ensureSingle(bar, 'text')
- .text(text)
- .attr({
- 'class': 'bartext bartext-' + textPosition,
- transform: '',
- 'text-anchor': 'middle',
- // prohibit tex interpretation until we can handle
- // tex and regular text together
- 'data-notex': 1
- })
- .call(Drawing.font, textFont)
- .call(svgTextUtils.convertToTspans, gd);
-
- return textSelection;
- }
-
- // get trace attributes
- var trace = calcTrace[0].trace;
- var isHorizontal = (trace.orientation === 'h');
-
- var text = getText(calcTrace, i, xa, ya);
- textPosition = getTextPosition(trace, i);
-
- // compute text position
- var inStackOrRelativeMode =
- opts.mode === 'stack' ||
- opts.mode === 'relative';
-
- var calcBar = calcTrace[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(calcTrace[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,
- // so that we can get correctly inside text scaling
- var di = bar.datum();
- if(isHorizontal) {
- if(xa.type === 'log' && di.s0 <= 0) {
- if(xa.range[0] < xa.range[1]) {
- x0 = 0;
- } else {
- x0 = xa._length;
- }
- }
- } else {
- if(ya.type === 'log' && di.s0 <= 0) {
- if(ya.range[0] < ya.range[1]) {
- y0 = ya._length;
- } else {
- y0 = 0;
- }
- }
- }
-
- // padding excluded
- var barWidth = Math.abs(x1 - x0) - 2 * TEXTPAD;
- var barHeight = Math.abs(y1 - y0) - 2 * TEXTPAD;
-
- var textSelection;
- var textBB;
- var textWidth;
- var textHeight;
-
- if(textPosition === 'outside') {
- if(!isOutmostBar && !calcBar.hasB) textPosition = 'inside';
- }
-
- if(textPosition === 'auto') {
- if(isOutmostBar) {
- // draw text using insideTextFont and check if it fits inside bar
- textPosition = 'inside';
- textSelection = appendTextNode(bar, text, insideTextFont);
-
- textBB = Drawing.bBox(textSelection.node()),
- textWidth = textBB.width,
- textHeight = textBB.height;
-
- var textHasSize = (textWidth > 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) {
- textSelection = appendTextNode(bar, text,
- (textPosition === 'outside') ?
- outsideTextFont : insideTextFont);
-
- textBB = Drawing.bBox(textSelection.node()),
- textWidth = textBB.width,
- textHeight = textBB.height;
-
- if(textWidth <= 0 || textHeight <= 0) {
- textSelection.remove();
- return;
- }
- }
-
- // compute text transform
- var transform, constrained;
- if(textPosition === 'outside') {
- constrained =
- trace.constraintext === 'both' ||
- trace.constraintext === 'outside';
-
- transform = getTransformToMoveOutsideBar(x0, x1, y0, y1, textBB, {
- isHorizontal: isHorizontal,
- constrained: constrained,
- angle: trace.textangle
- });
- } else {
- constrained =
- trace.constraintext === 'both' ||
- trace.constraintext === 'inside';
-
- transform = getTransformToMoveInsideBar(x0, x1, y0, y1, textBB, {
- isHorizontal: isHorizontal,
- constrained: constrained,
- angle: trace.textangle,
- anchor: trace.insidetextanchor
- });
- }
-
- textSelection.attr('transform', transform);
-}
-
-function getRotationFromAngle(angle) {
- return (angle === 'auto') ? 0 : angle;
-}
-
-function getTransformToMoveInsideBar(x0, x1, y0, y1, textBB, opts) {
- var isHorizontal = !!opts.isHorizontal;
- var constrained = !!opts.constrained;
- var angle = opts.angle || 0;
- var anchor = opts.anchor || 0;
-
- var textWidth = textBB.width;
- var textHeight = textBB.height;
- var lx = Math.abs(x1 - x0);
- var ly = Math.abs(y1 - y0);
-
- var textpad = (
- lx > (2 * TEXTPAD) &&
- ly > (2 * TEXTPAD)
- ) ? TEXTPAD : 0;
-
- lx -= 2 * textpad;
- ly -= 2 * textpad;
-
- var autoRotate = (angle === 'auto');
- var isAutoRotated = false;
- if(autoRotate &&
- !(textWidth <= lx && textHeight <= ly) &&
- (textWidth > lx || textHeight > ly) && (
- !(textWidth > ly || textHeight > lx) ||
- ((textWidth < textHeight) !== (lx < ly))
- )) {
- isAutoRotated = true;
- }
-
- if(isAutoRotated) {
- // don't rotate yet only swap bar width with height
- var tmp = ly;
- ly = lx;
- lx = tmp;
- }
-
- var rotation = getRotationFromAngle(angle);
- var absSin = Math.abs(Math.sin(Math.PI / 180 * rotation));
- var absCos = Math.abs(Math.cos(Math.PI / 180 * rotation));
-
- // compute and apply text padding
- var dx = Math.max(lx * absCos, ly * absSin);
- var dy = Math.max(lx * absSin, ly * absCos);
-
- var scale = (constrained) ?
- Math.min(dx / textWidth, dy / textHeight) :
- Math.max(absCos, absSin);
-
- scale = Math.min(1, scale);
-
- // compute text and target positions
- var targetX = (x0 + x1) / 2;
- var targetY = (y0 + y1) / 2;
-
- if(anchor !== 'middle') { // case of 'start' or 'end'
- var targetWidth = scale * (isHorizontal !== isAutoRotated ? textHeight : textWidth);
- var targetHeight = scale * (isHorizontal !== isAutoRotated ? textWidth : textHeight);
- textpad += 0.5 * (targetWidth * absSin + targetHeight * absCos);
-
- if(isHorizontal) {
- textpad *= dirSign(x0, x1);
- targetX = (anchor === 'start') ? x0 + textpad : x1 - textpad;
- } else {
- textpad *= dirSign(y0, y1);
- targetY = (anchor === 'start') ? y0 + textpad : y1 - textpad;
- }
- }
-
- var textX = (textBB.left + textBB.right) / 2;
- var textY = (textBB.top + textBB.bottom) / 2;
-
- // lastly apply auto rotation
- if(isAutoRotated) rotation += 90;
-
- return getTransform(textX, textY, targetX, targetY, scale, rotation);
-}
-
-function getTransformToMoveOutsideBar(x0, x1, y0, y1, textBB, opts) {
- var isHorizontal = !!opts.isHorizontal;
- var constrained = !!opts.constrained;
- var angle = opts.angle || 0;
-
- var textWidth = textBB.width;
- var textHeight = textBB.height;
- var lx = Math.abs(x1 - x0);
- var ly = Math.abs(y1 - y0);
-
- var textpad;
- // Keep the padding so the text doesn't sit right against
- // the bars, but don't factor it into barWidth
- if(isHorizontal) {
- textpad = (ly > 2 * TEXTPAD) ? TEXTPAD : 0;
- } else {
- textpad = (lx > 2 * TEXTPAD) ? TEXTPAD : 0;
- }
-
- // compute rotation and scale
- var scale = 1;
- if(constrained) {
- scale = (isHorizontal) ?
- Math.min(1, ly / textHeight) :
- Math.min(1, lx / textWidth);
- }
-
- var rotation = getRotationFromAngle(angle);
- var absSin = Math.abs(Math.sin(Math.PI / 180 * rotation));
- var absCos = Math.abs(Math.cos(Math.PI / 180 * rotation));
-
- // compute text and target positions
- var targetWidth = scale * (isHorizontal ? textHeight : textWidth);
- var targetHeight = scale * (isHorizontal ? textWidth : textHeight);
- textpad += 0.5 * (targetWidth * absSin + targetHeight * absCos);
-
- var targetX = (x0 + x1) / 2;
- var targetY = (y0 + y1) / 2;
-
- if(isHorizontal) {
- targetX = x1 - textpad * dirSign(x1, x0);
- } else {
- targetY = y1 + textpad * dirSign(y0, y1);
- }
-
- var textX = (textBB.left + textBB.right) / 2;
- var textY = (textBB.top + textBB.bottom) / 2;
-
- return getTransform(textX, textY, targetX, targetY, scale, rotation);
-}
-
-function getTransform(textX, textY, targetX, targetY, scale, rotation) {
- var transformScale;
- var transformRotate;
- var transformTranslate;
-
- if(scale < 1) transformScale = 'scale(' + scale + ') ';
- else {
- scale = 1;
- transformScale = '';
- }
-
- transformRotate = (rotation) ?
- 'rotate(' + rotation + ' ' + textX + ' ' + textY + ') ' : '';
-
- // Note that scaling also affects the center of the text box
- var translateX = (targetX - scale * textX);
- var translateY = (targetY - scale * textY);
- transformTranslate = 'translate(' + translateX + ' ' + translateY + ')';
-
- return transformTranslate + transformScale + transformRotate;
-}
-
-function getText(calcTrace, index, xa, ya) {
- var trace = calcTrace[0].trace;
-
- var value;
- if(!trace.textinfo) {
- value = helpers.getValue(trace.text, index);
- } else {
- value = calcTextinfo(calcTrace, index, xa, ya);
- }
-
- return helpers.coerceString(attributeText, value);
-}
-
-function getTextPosition(trace, index) {
- var value = helpers.getValue(trace.textposition, index);
- return helpers.coerceEnumerated(attributeTextPosition, value);
-}
-
-function calcTextinfo(calcTrace, index, xa, ya) {
- var trace = calcTrace[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 = calcTrace[index];
-
- var parts = textinfo.split('+');
- var text = [];
- var tx;
-
- var hasFlag = function(flag) { return parts.indexOf(flag) !== -1; };
-
- if(hasFlag('label')) {
- text.push(formatLabel(calcTrace[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,
- getTransformToMoveInsideBar: getTransformToMoveInsideBar,
- getTransformToMoveOutsideBar: getTransformToMoveOutsideBar
-};
-
-},{"../../components/color":51,"../../components/drawing":72,"../../lib":168,"../../lib/svg_text_utils":189,"../../plots/cartesian/axes":212,"../../registry":256,"./attributes":266,"./helpers":271,"./style":279,"d3":16,"fast-isnumeric":18}],277:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'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
- for(i = 0; i < cd.length; i++) {
- cd[i].selected = 0;
- }
- } else {
- for(i = 0; i < cd.length; i++) {
- var di = cd[i];
- var ct = 'ct' in di ? di.ct : getCentroid(di, xa, ya, isHorizontal, isFunnel);
-
- if(selectionTester.contains(ct, false, i, searchInfo)) {
- selection.push({
- pointNumber: i,
- x: xa.c2d(di.x),
- y: ya.c2d(di.y)
- });
- di.selected = 1;
- } else {
- di.selected = 0;
- }
- }
- }
-
- return selection;
-};
-
-function getCentroid(d, xa, ya, isHorizontal, isFunnel) {
- var x0 = xa.c2p(isHorizontal ? d.s0 : d.p0, true);
- var x1 = xa.c2p(isHorizontal ? d.s1 : d.p1, true);
- var y0 = ya.c2p(isHorizontal ? d.p0 : d.s0, true);
- var y1 = ya.c2p(isHorizontal ? d.p1 : d.s1, true);
-
- if(isFunnel) {
- return [(x0 + x1) / 2, (y0 + y1) / 2];
- } else {
- if(isHorizontal) {
- return [x1, (y0 + y1) / 2];
- } else {
- return [(x0 + x1) / 2, y1];
- }
- }
-}
-
-},{}],278:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = Sieve;
-
-var distinctVals = _dereq_('../../lib').distinctVals;
-var BADNUM = _dereq_('../../constants/numerical').BADNUM;
-
-/**
- * Helper class to sieve data from traces into bins
- *
- * @class
- *
- * @param {Array} traces
-* Array of calculated traces
- * @param {object} opts
- * - @param {boolean} [sepNegVal]
- * If true, then split data at the same position into a bar
- * for positive values and another for negative values
- * - @param {boolean} [overlapNoMerge]
- * If true, then don't merge overlapping bars into a single bar
- */
-function Sieve(traces, opts) {
- this.traces = traces;
- this.sepNegVal = opts.sepNegVal;
- this.overlapNoMerge = opts.overlapNoMerge;
-
- // for single-bin histograms - see histogram/calc
- var width1 = Infinity;
-
- var positions = [];
- for(var i = 0; i < traces.length; i++) {
- var trace = traces[i];
- for(var j = 0; j < trace.length; j++) {
- var bar = trace[j];
- if(bar.p !== BADNUM) positions.push(bar.p);
- }
- if(trace[0] && trace[0].width1) {
- width1 = Math.min(trace[0].width1, width1);
- }
- }
- this.positions = positions;
-
- var dv = distinctVals(positions);
- this.distinctPositions = dv.vals;
- if(dv.vals.length === 1 && width1 !== Infinity) this.minDiff = width1;
- else this.minDiff = Math.min(dv.minDiff, width1);
-
- this.binWidth = this.minDiff;
-
- this.bins = {};
-}
-
-/**
- * Sieve datum
- *
- * @method
- * @param {number} position
- * @param {number} value
- * @returns {number} Previous bin value
- */
-Sieve.prototype.put = function put(position, value) {
- var label = this.getLabel(position, value);
- var oldValue = this.bins[label] || 0;
-
- this.bins[label] = oldValue + value;
-
- return oldValue;
-};
-
-/**
- * Get current bin value for a given datum
- *
- * @method
- * @param {number} position Position of datum
- * @param {number} [value] Value of datum
- * (required if this.sepNegVal is true)
- * @returns {number} Current bin value
- */
-Sieve.prototype.get = function get(position, value) {
- var label = this.getLabel(position, value);
- return this.bins[label] || 0;
-};
-
-/**
- * Get bin label for a given datum
- *
- * @method
- * @param {number} position Position of datum
- * @param {number} [value] Value of datum
- * (required if this.sepNegVal is true)
- * @returns {string} Bin label
- * (prefixed with a 'v' if value is negative and this.sepNegVal is
- * true; otherwise prefixed with '^')
- */
-Sieve.prototype.getLabel = function getLabel(position, value) {
- var prefix = (value < 0 && this.sepNegVal) ? 'v' : '^';
- var label = (this.overlapNoMerge) ?
- position :
- Math.round(position / this.binWidth);
- return prefix + label;
-};
-
-},{"../../constants/numerical":149,"../../lib":168}],279:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var d3 = _dereq_('d3');
-var Color = _dereq_('../../components/color');
-var Drawing = _dereq_('../../components/drawing');
-var Lib = _dereq_('../../lib');
-var Registry = _dereq_('../../registry');
-
-var attributes = _dereq_('./attributes');
-var attributeTextFont = attributes.textfont;
-var attributeInsideTextFont = attributes.insidetextfont;
-var attributeOutsideTextFont = attributes.outsidetextfont;
-var helpers = _dereq_('./helpers');
-
-function style(gd, cd) {
- var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.barlayer').selectAll('g.trace');
- var barcount = s.size();
- var fullLayout = gd._fullLayout;
-
- // trace styling
- s.style('opacity', function(d) { return d[0].trace.opacity; })
-
- // for gapless (either stacked or neighboring grouped) bars use
- // crispEdges to turn off antialiasing so an artificial gap
- // isn't introduced.
- .each(function(d) {
- if((fullLayout.barmode === 'stack' && barcount > 1) ||
- (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 = determineFont(tx, d, trace, gd);
- Drawing.font(tx, font);
- });
-}
-
-function styleOnSelect(gd, cd) {
- var s = cd[0].node3;
- var trace = cd[0].trace;
-
- if(trace.selectedpoints) {
- stylePointsInSelectionMode(s, trace, gd);
- } else {
- stylePoints(s, trace, gd);
-
- Registry.getComponentMethod('errorbars', 'style')(s);
- }
-}
-
-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.extendFlat({}, 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
-};
-
-},{"../../components/color":51,"../../components/drawing":72,"../../lib":168,"../../registry":256,"./attributes":266,"./helpers":271,"d3":16}],280:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'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":51,"../../components/colorscale/defaults":61,"../../components/colorscale/helpers":62}],281:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var scatterAttrs = _dereq_('../scatter/attributes');
-var barAttrs = _dereq_('../bar/attributes');
-var colorAttrs = _dereq_('../../components/color/attributes');
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
-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',
-
- },
- name: {
- valType: 'string',
-
- editType: 'calc+clearAxisTypes',
-
- },
- text: extendFlat({}, scatterAttrs.text, {
-
- }),
- hovertext: extendFlat({}, scatterAttrs.hovertext, {
-
- }),
- hovertemplate: hovertemplateAttrs({
-
- }),
- whiskerwidth: {
- valType: 'number',
- min: 0,
- max: 1,
- dflt: 0.5,
-
- editType: 'calc',
-
- },
- notched: {
- valType: 'boolean',
-
- editType: 'calc',
-
- },
- notchwidth: {
- valType: 'number',
- min: 0,
- max: 0.5,
- dflt: 0.25,
-
- editType: 'calc',
-
- },
- boxpoints: {
- valType: 'enumerated',
- values: ['all', 'outliers', 'suspectedoutliers', false],
- dflt: 'outliers',
-
- editType: 'calc',
-
- },
- boxmean: {
- valType: 'enumerated',
- values: [true, 'sd', false],
- dflt: false,
-
- editType: 'calc',
-
- },
- jitter: {
- valType: 'number',
- min: 0,
- max: 1,
-
- editType: 'calc',
-
- },
- pointpos: {
- valType: 'number',
- min: -2,
- max: 2,
-
- editType: 'calc',
-
- },
- orientation: {
- valType: 'enumerated',
- values: ['v', 'h'],
-
- editType: 'calc+clearAxisTypes',
-
- },
-
- 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,
-
- offsetgroup: barAttrs.offsetgroup,
- alignmentgroup: barAttrs.alignmentgroup,
-
- selected: {
- marker: scatterAttrs.selected.marker,
- editType: 'style'
- },
- unselected: {
- marker: scatterAttrs.unselected.marker,
- editType: 'style'
- },
- hoveron: {
- valType: 'flaglist',
- flags: ['boxes', 'points'],
- dflt: 'boxes+points',
-
- editType: 'style',
-
- }
-};
-
-},{"../../components/color/attributes":50,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../bar/attributes":266,"../scatter/attributes":365}],282:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var isNumeric = _dereq_('fast-isnumeric');
-
-var Lib = _dereq_('../../lib');
-var _ = Lib._;
-var Axes = _dereq_('../../plots/cartesian/axes');
-
-// outlier definition based on http://www.physics.csbsju.edu/stats/box2.html
-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
- var numKey = trace.type === 'violin' ? '_numViolins' : '_numBoxes';
-
- var i;
- 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 val = valAxis.makeCalcdata(trace, valLetter);
- var pos = getPos(trace, posLetter, posAxis, val, fullLayout[numKey]);
-
- var dv = Lib.distinctVals(pos);
- var posDistinct = dv.vals;
- var dPos = dv.minDiff / 2;
- var posBins = makeBins(posDistinct, dPos);
-
- var pLen = posDistinct.length;
- var ptsPerBin = initNestedArray(pLen);
-
- // bin pts info per position bins
- for(i = 0; i < trace._length; i++) {
- var v = val[i];
- if(!isNumeric(v)) continue;
-
- var n = Lib.findBin(pos[i], posBins);
- if(n >= 0 && n < pLen) {
- var pt = {v: v, i: i};
- arraysToCalcdata(pt, trace, i);
- ptsPerBin[n].push(pt);
- }
- }
-
- var cdi;
- var ptFilterFn = (trace.boxpoints || trace.points) === 'all' ?
- Lib.identity :
- function(pt) { return (pt.v < cdi.lf || pt.v > cdi.uf); };
-
- // build calcdata trace items, one item per distinct position
- for(i = 0; i < pLen; i++) {
- if(ptsPerBin[i].length > 0) {
- var pts = ptsPerBin[i].sort(sortByVal);
- var boxVals = pts.map(extractVal);
- var bvLen = boxVals.length;
-
- cdi = {};
- cdi.pos = posDistinct[i];
- cdi.pts = pts;
-
- // Sort categories by values
- cdi[posLetter] = cdi.pos;
- cdi[valLetter] = cdi.pts.map(function(pt) { return pt.v; });
-
- cdi.min = boxVals[0];
- cdi.max = boxVals[bvLen - 1];
- cdi.mean = Lib.mean(boxVals, bvLen);
- cdi.sd = Lib.stdev(boxVals, bvLen, cdi.mean);
-
- // first quartile
- cdi.q1 = Lib.interp(boxVals, 0.25);
- // median
- cdi.med = Lib.interp(boxVals, 0.5);
- // third quartile
- cdi.q3 = Lib.interp(boxVals, 0.75);
-
- // lower and upper fences - last point inside
- // 1.5 interquartile ranges from quartiles
- cdi.lf = Math.min(
- cdi.q1,
- boxVals[Math.min(
- Lib.findBin(2.5 * cdi.q1 - 1.5 * cdi.q3, boxVals, true) + 1,
- bvLen - 1
- )]
- );
- cdi.uf = Math.max(
- cdi.q3,
- boxVals[Math.max(
- Lib.findBin(2.5 * cdi.q3 - 1.5 * cdi.q1, boxVals),
- 0
- )]
- );
-
- // lower and upper outliers - 3 IQR out (don't clip to max/min,
- // this is only for discriminating suspected & far outliers)
- cdi.lo = 4 * cdi.q1 - 3 * cdi.q3;
- cdi.uo = 4 * cdi.q3 - 3 * cdi.q1;
-
- // lower and upper notches ~95% Confidence Intervals for median
- var iqr = cdi.q3 - cdi.q1;
- var mci = 1.57 * iqr / Math.sqrt(bvLen);
- cdi.ln = cdi.med - mci;
- cdi.un = cdi.med + mci;
-
- cdi.pts2 = pts.filter(ptFilterFn);
-
- cd.push(cdi);
- }
- }
-
- calcSelection(cd, trace);
- var extremes = Axes.findExtremes(valAxis, val, {padded: true});
- trace._extremes[valAxis._id] = extremes;
-
- 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:
-// if no x (y) data, use x0 (y0), or name
-// so if you want one box
-// per trace, set x0 (y0) to the x (y) value or category for this trace
-// (or set x (y) to a constant array matching y (x))
-function getPos(trace, posLetter, posAxis, val, num) {
- if(posLetter in trace) {
- return posAxis.makeCalcdata(trace, posLetter);
- }
-
- var pos0;
-
- if(posLetter + '0' in trace) {
- 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']);
-
- return val.map(function() { return pos0c; });
-}
-
-function makeBins(x, dx) {
- var len = x.length;
- var bins = new Array(len + 1);
-
- for(var i = 0; i < len; i++) {
- bins[i] = x[i] - dx;
- }
- bins[len] = x[len - 1] + dx;
-
- return bins;
-}
-
-function initNestedArray(len) {
- var arr = new Array(len);
- for(var i = 0; i < len; i++) {
- arr[i] = [];
- }
- return arr;
-}
-
-function arraysToCalcdata(pt, trace, i) {
- var trace2calc = {
- text: 'tx',
- hovertext: 'htx'
- };
-
- for(var k in trace2calc) {
- if(Array.isArray(trace[k])) {
- pt[trace2calc[k]] = trace[k][i];
- }
- }
-}
-
-function calcSelection(cd, trace) {
- if(Lib.isArrayOrTypedArray(trace.selectedpoints)) {
- for(var i = 0; i < cd.length; i++) {
- var pts = cd[i].pts || [];
- var ptNumber2cdIndex = {};
-
- for(var j = 0; j < pts.length; j++) {
- ptNumber2cdIndex[pts[j].i] = j;
- }
-
- Lib.tagSelected(pts, trace, ptNumber2cdIndex);
- }
- }
-}
-
-function sortByVal(a, b) { return a.v - b.v; }
-
-function extractVal(o) { return o.v; }
-
-},{"../../lib":168,"../../plots/cartesian/axes":212,"fast-isnumeric":18}],283:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Axes = _dereq_('../../plots/cartesian/axes');
-var Lib = _dereq_('../../lib');
-var getAxisGroup = _dereq_('../../plots/cartesian/axis_ids').getAxisGroup;
-
-var orientations = ['v', 'h'];
-
-function crossTraceCalc(gd, plotinfo) {
- var calcdata = gd.calcdata;
- var xa = plotinfo.xaxis;
- var ya = plotinfo.yaxis;
-
- for(var i = 0; i < orientations.length; i++) {
- var orientation = orientations[i];
- var posAxis = orientation === 'h' ? ya : xa;
- var boxList = [];
-
- // make list of boxes / candlesticks
- // For backward compatibility, candlesticks are treated as if they *are* box traces here
- for(var j = 0; j < calcdata.length; j++) {
- var cd = calcdata[j];
- var t = cd[0].t;
- var trace = cd[0].trace;
-
- if(trace.visible === true &&
- (trace.type === 'box' || trace.type === 'candlestick') &&
- !t.empty &&
- (trace.orientation || 'v') === orientation &&
- trace.xaxis === xa._id &&
- trace.yaxis === ya._id
- ) {
- boxList.push(j);
- }
- }
-
- setPositionOffset('box', gd, boxList, posAxis);
- }
-}
-
-function setPositionOffset(traceType, gd, boxList, posAxis) {
- var calcdata = gd.calcdata;
- var fullLayout = gd._fullLayout;
- var axId = posAxis._id;
- var axLetter = axId.charAt(0);
-
- var i, j, calcTrace;
- var pointList = [];
- var shownPts = 0;
-
- // make list of box points
- for(i = 0; i < boxList.length; i++) {
- calcTrace = calcdata[boxList[i]];
- for(j = 0; j < calcTrace.length; j++) {
- pointList.push(calcTrace[j].pos);
- shownPts += (calcTrace[j].pts2 || []).length;
- }
- }
-
- if(!pointList.length) return;
-
- // box plots - update dPos based on multiple traces
- var boxdv = Lib.distinctVals(pointList);
- var dPos0 = boxdv.minDiff / 2;
-
- // check for forced minimum dtick
- Axes.minDtick(posAxis, boxdv.minDiff, boxdv.vals[0], true);
-
- var numKey = traceType === 'violin' ? '_numViolins' : '_numBoxes';
- var numTotal = fullLayout[numKey];
- var group = fullLayout[traceType + 'mode'] === 'group' && numTotal > 1;
- var groupFraction = 1 - fullLayout[traceType + 'gap'];
- var groupGapFraction = 1 - fullLayout[traceType + 'groupgap'];
-
- for(i = 0; i < boxList.length; i++) {
- calcTrace = calcdata[boxList[i]];
-
- var trace = calcTrace[0].trace;
- var t = calcTrace[0].t;
- var width = trace.width;
- var side = trace.side;
-
- // position coordinate delta
- var dPos;
- // box half width;
- var bdPos;
- // box center offset
- var bPos;
- // half-width within which to accept hover for this box/violin
- // always split the distance to the closest box/violin
- var wHover;
-
- if(width) {
- dPos = bdPos = wHover = width / 2;
- bPos = 0;
- } else {
- dPos = dPos0;
-
- if(group) {
- var groupId = getAxisGroup(fullLayout, posAxis._id) + trace.orientation;
- var alignmentGroups = fullLayout._alignmentOpts[groupId] || {};
- var alignmentGroupOpts = alignmentGroups[trace.alignmentgroup] || {};
- var nOffsetGroups = Object.keys(alignmentGroupOpts.offsetGroups || {}).length;
- var num = nOffsetGroups || numTotal;
- var shift = nOffsetGroups ? trace._offsetIndex : t.num;
-
- bdPos = dPos * groupFraction * groupGapFraction / num;
- bPos = 2 * dPos * (-0.5 + (shift + 0.5) / num) * groupFraction;
- wHover = dPos * groupFraction / num;
- } else {
- bdPos = dPos * groupFraction * groupGapFraction;
- bPos = 0;
- wHover = dPos;
- }
- }
- t.dPos = dPos;
- t.bPos = bPos;
- t.bdPos = bdPos;
- t.wHover = wHover;
-
- // box/violin-only value-space push value
- var pushplus;
- var pushminus;
- // edge of box/violin
- var edge = bPos + bdPos;
- var edgeplus;
- var edgeminus;
- // value-space padding
- var vpadplus;
- var vpadminus;
- // pixel-space padding
- var ppadplus;
- var ppadminus;
- // do we add 5% of both sides (more logic for points beyond box/violin below)
- var padded = Boolean(width);
- // does this trace show points?
- var hasPts = (trace.boxpoints || trace.points) && (shownPts > 0);
-
- 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
- padded = true;
- ppadplus = ms;
- vpadplus = pp;
- } else if(pp > edgeplus) {
- // (+), use push-value (it's bigger), but add px-pad
- ppadplus = ms;
- vpadplus = pushplus;
- }
- }
- if(pp <= pushplus) {
- // (->) fallback to push value
- vpadplus = pushplus;
- }
-
- var pm = 0;
- if((pointpos - jitter) <= 0) {
- pm = -edge * (pointpos - jitter);
- if(pm > pushminus) {
- // (--) beyond plus-value, use pp
- padded = true;
- ppadminus = ms;
- vpadminus = pm;
- } else if(pm > edgeminus) {
- // (-), use push-value (it's bigger), but add px-pad
- ppadminus = ms;
- vpadminus = pushminus;
- }
- }
- if(pm <= pushminus) {
- // (<-) fallback to push value
- vpadminus = pushminus;
- }
- } else {
- vpadplus = pushplus;
- vpadminus = pushminus;
- }
-
- var pos = new Array(calcTrace.length);
- for(j = 0; j < calcTrace.length; j++) {
- pos[j] = calcTrace[j].pos;
- }
-
- trace._extremes[axId] = Axes.findExtremes(posAxis, pos, {
- padded: padded,
- vpadminus: vpadminus,
- vpadplus: vpadplus,
- // N.B. SVG px-space positive/negative
- ppadminus: {x: ppadminus, y: ppadplus}[axLetter],
- ppadplus: {x: ppadplus, y: ppadminus}[axLetter],
- });
- }
-}
-
-module.exports = {
- crossTraceCalc: crossTraceCalc,
- setPositionOffset: setPositionOffset
-};
-
-},{"../../lib":168,"../../plots/cartesian/axes":212,"../../plots/cartesian/axis_ids":215}],284:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var Registry = _dereq_('../../registry');
-var Color = _dereq_('../../components/color');
-var handleGroupingDefaults = _dereq_('../bar/defaults').handleGroupingDefaults;
-var attributes = _dereq_('./attributes');
-
-function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
- function coerce(attr, dflt) {
- return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
- }
-
- handleSampleDefaults(traceIn, traceOut, coerce, layout);
- if(traceOut.visible === false) return;
-
- coerce('line.color', (traceIn.marker || {}).color || defaultColor);
- coerce('line.width');
- coerce('fillcolor', Color.addOpacity(traceOut.line.color, 0.5));
-
- coerce('whiskerwidth');
- coerce('boxmean');
- coerce('width');
-
- var notched = coerce('notched', traceIn.notchwidth !== undefined);
- if(notched) coerce('notchwidth');
-
- handlePointsDefaults(traceIn, traceOut, coerce, {prefix: 'box'});
-}
-
-function handleSampleDefaults(traceIn, traceOut, coerce, layout) {
- var y = coerce('y');
- var x = coerce('x');
- var hasX = x && x.length;
-
- var defaultOrientation, len;
-
- if(y && y.length) {
- defaultOrientation = 'v';
- if(hasX) {
- len = Math.min(Lib.minRowLength(x), Lib.minRowLength(y));
- } else {
- coerce('x0');
- len = Lib.minRowLength(y);
- }
- } else if(hasX) {
- defaultOrientation = 'h';
- coerce('y0');
- len = Lib.minRowLength(x);
- } else {
- traceOut.visible = false;
- return;
- }
- traceOut._length = len;
-
- var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults');
- handleCalendarDefaults(traceIn, traceOut, ['x', 'y'], layout);
-
- coerce('orientation', defaultOrientation);
-}
-
-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 points = coerce(
- prefix + 'points',
- (outlierColorDflt || lineoutliercolor) ? 'suspectedoutliers' : undefined
- );
-
- if(points) {
- coerce('jitter', points === 'all' ? 0.3 : 0);
- coerce('pointpos', points === '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(points === '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; i < fullData.length; i++) {
- traceOut = fullData[i];
- var traceType = traceOut.type;
-
- if(traceType === 'box' || traceType === 'violin') {
- traceIn = traceOut._input;
- if(fullLayout[traceType + 'mode'] === 'group') {
- handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce);
- }
- }
- }
-}
-
-module.exports = {
- supplyDefaults: supplyDefaults,
- crossTraceDefaults: crossTraceDefaults,
-
- handleSampleDefaults: handleSampleDefaults,
- handlePointsDefaults: handlePointsDefaults
-};
-
-},{"../../components/color":51,"../../lib":168,"../../registry":256,"../bar/defaults":270,"./attributes":281}],285:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = function eventData(out, pt) {
- // Note: hoverOnBox property is needed for click-to-select
- // to ignore when a box was clicked. This is the reason box
- // implements this custom eventData function.
- if(pt.hoverOnBox) out.hoverOnBox = pt.hoverOnBox;
-
- if('xVal' in pt) out.x = pt.xVal;
- if('yVal' in pt) out.y = pt.yVal;
- if(pt.xa) out.xaxis = pt.xa;
- if(pt.ya) out.yaxis = pt.ya;
-
- return out;
-};
-
-},{}],286:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Axes = _dereq_('../../plots/cartesian/axes');
-var Lib = _dereq_('../../lib');
-var Fx = _dereq_('../../components/fx');
-var Color = _dereq_('../../components/color');
-var fillText = Lib.fillText;
-
-function hoverPoints(pointData, xval, yval, hovermode) {
- var cd = pointData.cd;
- var trace = cd[0].trace;
- var hoveron = trace.hoveron;
- var closeBoxData = [];
- var closePtData;
-
- if(hoveron.indexOf('boxes') !== -1) {
- closeBoxData = closeBoxData.concat(hoverOnBoxes(pointData, xval, yval, hovermode));
- }
-
- if(hoveron.indexOf('points') !== -1) {
- closePtData = hoverOnPoints(pointData, xval, yval);
- }
-
- // If there's a point in range and hoveron has points, show the best single point only.
- // If hoveron has boxes and there's no point in range (or hoveron doesn't have points), show the box stats.
- if(hovermode === 'closest') {
- if(closePtData) return [closePtData];
- return closeBoxData;
- }
-
- // Otherwise in compare mode, allow a point AND the box stats to be labeled
- // If there are multiple boxes in range (ie boxmode = 'overlay') we'll see stats for all of them.
- if(closePtData) {
- closeBoxData.push(closePtData);
- return closeBoxData;
- }
- return closeBoxData;
-}
-
-function hoverOnBoxes(pointData, xval, yval, hovermode) {
- var cd = pointData.cd;
- var xa = pointData.xa;
- var ya = pointData.ya;
- var trace = cd[0].trace;
- var t = cd[0].t;
- var isViolin = trace.type === 'violin';
- var closeBoxData = [];
-
- var pLetter, vLetter, pAxis, vAxis, vVal, pVal, dx, dy, dPos,
- hoverPseudoDistance, spikePseudoDistance;
-
- var boxDelta = t.bdPos;
- var boxDeltaPos, boxDeltaNeg;
- var posAcceptance = t.wHover;
- var shiftPos = function(di) { return di.pos + t.bPos - pVal; };
-
- if(isViolin && trace.side !== 'both') {
- if(trace.side === 'positive') {
- dPos = function(di) {
- var pos = shiftPos(di);
- return Fx.inbox(pos, pos + posAcceptance, hoverPseudoDistance);
- };
- boxDeltaPos = boxDelta;
- boxDeltaNeg = 0;
- }
- if(trace.side === 'negative') {
- dPos = function(di) {
- var pos = shiftPos(di);
- return Fx.inbox(pos - posAcceptance, pos, hoverPseudoDistance);
- };
- boxDeltaPos = 0;
- boxDeltaNeg = boxDelta;
- }
- } else {
- dPos = function(di) {
- var pos = shiftPos(di);
- return Fx.inbox(pos - posAcceptance, pos + posAcceptance, hoverPseudoDistance);
- };
- boxDeltaPos = boxDeltaNeg = boxDelta;
- }
-
- var dVal;
-
- if(isViolin) {
- dVal = function(di) {
- return Fx.inbox(di.span[0] - vVal, di.span[1] - vVal, hoverPseudoDistance);
- };
- } else {
- dVal = function(di) {
- return Fx.inbox(di.min - vVal, di.max - vVal, hoverPseudoDistance);
- };
- }
-
- if(trace.orientation === 'h') {
- vVal = xval;
- pVal = yval;
- dx = dVal;
- dy = dPos;
- pLetter = 'y';
- pAxis = ya;
- vLetter = 'x';
- vAxis = xa;
- } else {
- vVal = yval;
- pVal = xval;
- dx = dPos;
- dy = dVal;
- pLetter = 'x';
- pAxis = xa;
- vLetter = 'y';
- vAxis = ya;
- }
-
- // if two boxes are overlaying, let the narrowest one win
- var pseudoDistance = Math.min(1, boxDelta / Math.abs(pAxis.r2c(pAxis.range[1]) - pAxis.r2c(pAxis.range[0])));
- hoverPseudoDistance = pointData.maxHoverDistance - pseudoDistance;
- spikePseudoDistance = pointData.maxSpikeDistance - pseudoDistance;
-
- 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
- // and create the item(s) in closedata for this point
- if(pointData.index === false) return [];
-
- var di = cd[pointData.index];
- var lc = trace.line.color;
- var mc = (trace.marker || {}).color;
-
- if(Color.opacity(lc) && trace.line.width) pointData.color = lc;
- else if(Color.opacity(mc) && trace.boxpoints) pointData.color = mc;
- else pointData.color = trace.fillcolor;
-
- pointData[pLetter + '0'] = pAxis.c2p(di.pos + t.bPos - boxDeltaNeg, true);
- pointData[pLetter + '1'] = pAxis.c2p(di.pos + t.bPos + boxDeltaPos, true);
-
- pointData[pLetter + 'LabelVal'] = di.pos;
-
- var spikePosAttr = pLetter + 'Spike';
- pointData.spikeDistance = dxy(di) * spikePseudoDistance / hoverPseudoDistance;
- pointData[spikePosAttr] = pAxis.c2p(di.pos, true);
-
- // box plots: each "point" gets many labels
- var usedVals = {};
- var attrs = ['med', 'min', 'q1', 'q3', 'max'];
-
- if(trace.boxmean || (trace.meanline || {}).visible) {
- attrs.push('mean');
- }
- if(trace.boxpoints || trace.points) {
- attrs.push('lf', 'uf');
- }
-
- for(var i = 0; i < attrs.length; i++) {
- var attr = attrs[i];
-
- if(!(attr in di) || (di[attr] in usedVals)) continue;
- usedVals[di[attr]] = true;
-
- // copy out to a new object for each value to label
- var val = di[attr];
- var valPx = vAxis.c2p(val, true);
- var pointData2 = Lib.extendFlat({}, pointData);
-
- pointData2[vLetter + '0'] = pointData2[vLetter + '1'] = valPx;
- pointData2[vLetter + 'LabelVal'] = val;
- pointData2[vLetter + 'Label'] = (t.labels ? t.labels[attr] + ' ' : '') + Axes.hoverLabelText(vAxis, val);
-
- // Note: introduced to be able to distinguish a
- // clicked point from a box during click-to-select
- pointData2.hoverOnBox = true;
-
- if(attr === 'mean' && ('sd' in di) && trace.boxmean === 'sd') {
- pointData2[vLetter + 'err'] = di.sd;
- }
-
- // only keep name and spikes on the first item (median)
- pointData.name = '';
- pointData.spikeDistance = undefined;
- pointData[spikePosAttr] = undefined;
-
- // no hovertemplate support yet
- pointData2.hovertemplate = false;
-
- closeBoxData.push(pointData2);
- }
-
- return closeBoxData;
-}
-
-function hoverOnPoints(pointData, xval, yval) {
- var cd = pointData.cd;
- var xa = pointData.xa;
- var ya = pointData.ya;
- var trace = cd[0].trace;
- var xPx = xa.c2p(xval);
- var yPx = ya.c2p(yval);
- var closePtData;
-
- var dx = function(di) {
- var rad = Math.max(3, di.mrc || 0);
- return Math.max(Math.abs(xa.c2p(di.x) - xPx) - rad, 1 - 3 / rad);
- };
- var dy = function(di) {
- var rad = Math.max(3, di.mrc || 0);
- return Math.max(Math.abs(ya.c2p(di.y) - yPx) - rad, 1 - 3 / rad);
- };
- var distfn = Fx.quadrature(dx, dy);
-
- // show one point per trace
- var ijClosest = false;
- var di, pt;
-
- for(var i = 0; i < cd.length; i++) {
- di = cd[i];
-
- for(var j = 0; j < (di.pts || []).length; j++) {
- pt = di.pts[j];
-
- var newDistance = distfn(pt);
- if(newDistance <= pointData.distance) {
- pointData.distance = newDistance;
- ijClosest = [i, j];
- }
- }
- }
-
- if(!ijClosest) return false;
-
- di = cd[ijClosest[0]];
- pt = di.pts[ijClosest[1]];
-
- var xc = xa.c2p(pt.x, true);
- var yc = ya.c2p(pt.y, true);
- var rad = pt.mrc || 1;
-
- closePtData = Lib.extendFlat({}, pointData, {
- // corresponds to index in x/y input data array
- index: pt.i,
- color: (trace.marker || {}).color,
- name: trace.name,
- x0: xc - rad,
- x1: xc + rad,
- y0: yc - rad,
- y1: yc + rad,
- spikeDistance: pointData.distance,
- hovertemplate: trace.hovertemplate
- });
-
- var pa;
- if(trace.orientation === 'h') {
- pa = ya;
- closePtData.xLabelVal = pt.x;
- closePtData.yLabelVal = di.pos;
- } else {
- pa = xa;
- closePtData.xLabelVal = di.pos;
- closePtData.yLabelVal = pt.y;
- }
-
- var pLetter = pa._id.charAt(0);
- closePtData[pLetter + 'Spike'] = pa.c2p(di.pos, true);
-
- fillText(pt, trace, closePtData);
-
- return closePtData;
-}
-
-module.exports = {
- hoverPoints: hoverPoints,
- hoverOnBoxes: hoverOnBoxes,
- hoverOnPoints: hoverOnPoints
-};
-
-},{"../../components/color":51,"../../components/fx":90,"../../lib":168,"../../plots/cartesian/axes":212}],287:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = {
- attributes: _dereq_('./attributes'),
- layoutAttributes: _dereq_('./layout_attributes'),
- supplyDefaults: _dereq_('./defaults').supplyDefaults,
- crossTraceDefaults: _dereq_('./defaults').crossTraceDefaults,
- supplyLayoutDefaults: _dereq_('./layout_defaults').supplyLayoutDefaults,
- calc: _dereq_('./calc'),
- crossTraceCalc: _dereq_('./cross_trace_calc').crossTraceCalc,
- 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: 'box',
- basePlotModule: _dereq_('../../plots/cartesian'),
- categories: ['cartesian', 'svg', 'symbols', 'oriented', 'box-violin', 'showLegend', 'boxLayout', 'zoomScale'],
- meta: {
-
- }
-};
-
-},{"../../plots/cartesian":223,"./attributes":281,"./calc":282,"./cross_trace_calc":283,"./defaults":284,"./event_data":285,"./hover":286,"./layout_attributes":288,"./layout_defaults":289,"./plot":290,"./select":291,"./style":292}],288:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-
-module.exports = {
- boxmode: {
- valType: 'enumerated',
- values: ['group', 'overlay'],
- dflt: 'overlay',
-
- editType: 'calc',
-
- },
- boxgap: {
- valType: 'number',
- min: 0,
- max: 1,
- dflt: 0.3,
-
- editType: 'calc',
-
- },
- boxgroupgap: {
- valType: 'number',
- min: 0,
- max: 1,
- dflt: 0.3,
-
- editType: 'calc',
-
- }
-};
-
-},{}],289:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Registry = _dereq_('../../registry');
-var Lib = _dereq_('../../lib');
-var layoutAttributes = _dereq_('./layout_attributes');
-
-function _supply(layoutIn, layoutOut, fullData, coerce, traceType) {
- var category = traceType + 'Layout';
- var hasTraceType = false;
-
- for(var i = 0; i < fullData.length; i++) {
- var trace = fullData[i];
-
- if(Registry.traceIs(trace, category)) {
- hasTraceType = true;
- break;
- }
- }
- if(!hasTraceType) return;
-
- coerce(traceType + 'mode');
- coerce(traceType + 'gap');
- coerce(traceType + 'groupgap');
-}
-
-function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
- function coerce(attr, dflt) {
- return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt);
- }
- _supply(layoutIn, layoutOut, fullData, coerce, 'box');
-}
-
-module.exports = {
- supplyLayoutDefaults: supplyLayoutDefaults,
- _supply: _supply
-};
-
-},{"../../lib":168,"../../registry":256,"./layout_attributes":288}],290:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var d3 = _dereq_('d3');
-
-var Lib = _dereq_('../../lib');
-var Drawing = _dereq_('../../components/drawing');
-
-// constants for dynamic jitter (ie less jitter for sparser points)
-var JITTERCOUNT = 5; // points either side of this to include
-var JITTERSPREAD = 0.01; // fraction of IQR to count as "dense"
-
-function plot(gd, plotinfo, cdbox, boxLayer) {
- var xa = plotinfo.xaxis;
- var ya = plotinfo.yaxis;
-
- Lib.makeTraceGroups(boxLayer, cdbox, 'trace boxes').each(function(cd) {
- var plotGroup = d3.select(this);
- var cd0 = cd[0];
- var t = cd0.t;
- var trace = cd0.trace;
- if(!plotinfo.isRangePlot) cd0.node3 = plotGroup;
-
- // whisker width
- t.wdPos = t.bdPos * trace.whiskerwidth;
-
- if(trace.visible !== true || t.empty) {
- plotGroup.remove();
- return;
- }
-
- var posAxis, valAxis;
-
- if(trace.orientation === 'h') {
- posAxis = ya;
- valAxis = xa;
- } else {
- posAxis = xa;
- valAxis = ya;
- }
-
- plotBoxAndWhiskers(plotGroup, {pos: posAxis, val: valAxis}, trace, t);
- plotPoints(plotGroup, {x: xa, y: ya}, trace, t);
- plotBoxMean(plotGroup, {pos: posAxis, val: valAxis}, trace, t);
- });
-}
-
-function plotBoxAndWhiskers(sel, axes, trace, t) {
- var posAxis = axes.pos;
- var valAxis = axes.val;
- var bPos = t.bPos;
- var wdPos = t.wdPos || 0;
- var bPosPxOffset = t.bPosPxOffset || 0;
- var whiskerWidth = trace.whiskerwidth || 0;
- var notched = trace.notched || false;
- var nw = notched ? 1 - 2 * trace.notchwidth : 1;
-
- // to support for one-sided box
- var 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.box').data((
- trace.type !== 'violin' ||
- trace.box.visible
- ) ? Lib.identity : []);
-
- paths.enter().append('path')
- .style('vector-effect', 'non-scaling-stroke')
- .attr('class', 'box');
-
- paths.exit().remove();
-
- paths.each(function(d) {
- if(d.empty) return 'M0,0Z';
-
- var pos = d.pos;
- var posc = posAxis.c2p(pos + bPos, true) + bPosPxOffset;
- var pos0 = posAxis.c2p(pos + bPos - bdPos0, true) + bPosPxOffset;
- var pos1 = posAxis.c2p(pos + bPos + bdPos1, true) + bPosPxOffset;
- var posw0 = posAxis.c2p(pos + bPos - wdPos, true) + bPosPxOffset;
- var posw1 = posAxis.c2p(pos + bPos + wdPos, true) + bPosPxOffset;
- var posm0 = posAxis.c2p(pos + bPos - bdPos0 * nw, true) + bPosPxOffset;
- var posm1 = posAxis.c2p(pos + bPos + bdPos1 * nw, true) + bPosPxOffset;
- var q1 = valAxis.c2p(d.q1, true);
- var q3 = valAxis.c2p(d.q3, true);
- // make sure median isn't identical to either of the
- // quartiles, so we can see it
- var m = Lib.constrain(
- valAxis.c2p(d.med, true),
- Math.min(q1, q3) + 1, Math.max(q1, q3) - 1
- );
-
- // for compatibility with box, violin, and candlestick
- // perhaps we should put this into cd0.t instead so it's more explicit,
- // but what we have now is:
- // - box always has d.lf, but boxpoints can be anything
- // - violin has d.lf and should always use it (boxpoints is undefined)
- // - candlestick has only min/max
- var useExtremes = (d.lf === undefined) || (trace.boxpoints === false);
- var lf = valAxis.c2p(useExtremes ? d.min : d.lf, true);
- var uf = valAxis.c2p(useExtremes ? d.max : d.uf, true);
- var ln = valAxis.c2p(d.ln, true);
- var un = valAxis.c2p(d.un, true);
-
- if(trace.orientation === 'h') {
- d3.select(this).attr('d',
- 'M' + m + ',' + posm0 + 'V' + posm1 + // median line
- 'M' + q1 + ',' + pos0 + 'V' + pos1 + // left edge
- (notched ? 'H' + ln + 'L' + m + ',' + posm1 + 'L' + un + ',' + pos1 : '') + // top notched edge
- 'H' + q3 + // end of the top edge
- 'V' + pos0 + // right edge
- (notched ? 'H' + un + 'L' + m + ',' + posm0 + 'L' + ln + ',' + pos0 : '') + // bottom notched edge
- 'Z' + // end of the box
- 'M' + q1 + ',' + posc + 'H' + lf + 'M' + q3 + ',' + posc + 'H' + uf + // whiskers
- ((whiskerWidth === 0) ? '' : // whisker caps
- 'M' + lf + ',' + posw0 + 'V' + posw1 + 'M' + uf + ',' + posw0 + 'V' + posw1));
- } else {
- d3.select(this).attr('d',
- 'M' + posm0 + ',' + m + 'H' + posm1 + // median line
- 'M' + pos0 + ',' + q1 + 'H' + pos1 + // top of the box
- (notched ? 'V' + ln + 'L' + posm1 + ',' + m + 'L' + pos1 + ',' + un : '') + // notched right edge
- 'V' + q3 + // end of the right edge
- 'H' + pos0 + // bottom of the box
- (notched ? 'V' + un + 'L' + posm0 + ',' + m + 'L' + pos0 + ',' + ln : '') + // notched left edge
- 'Z' + // end of the box
- 'M' + posc + ',' + q1 + 'V' + lf + 'M' + posc + ',' + q3 + 'V' + uf + // whiskers
- ((whiskerWidth === 0) ? '' : // whisker caps
- 'M' + posw0 + ',' + lf + 'H' + posw1 + 'M' + posw0 + ',' + uf + 'H' + posw1));
- }
- });
-}
-
-function plotPoints(sel, axes, trace, t) {
- var xa = axes.x;
- var ya = axes.y;
- var bdPos = t.bdPos;
- var bPos = t.bPos;
-
- // to support violin points
- var mode = trace.boxpoints || trace.points;
-
- // repeatable pseudo-random number generator
- Lib.seedPseudoRandom();
-
- // since box plot points get an extra level of nesting, each
- // box needs the trace styling info
- var fn = function(d) {
- d.forEach(function(v) {
- v.t = t;
- v.trace = trace;
- });
- return d;
- };
-
- var gPoints = sel.selectAll('g.points')
- .data(mode ? fn : []);
-
- gPoints.enter().append('g')
- .attr('class', 'points');
-
- gPoints.exit().remove();
-
- var paths = gPoints.selectAll('path')
- .data(function(d) {
- var i;
- var pts = d.pts2;
-
- // normally use IQR, but if this is 0 or too small, use max-min
- var typicalSpread = Math.max((d.max - d.min) / 10, d.q3 - d.q1);
- var minSpread = typicalSpread * 1e-9;
- var spreadLimit = typicalSpread * JITTERSPREAD;
- var jitterFactors = [];
- var maxJitterFactor = 0;
- var newJitter;
-
- // dynamic jitter
- if(trace.jitter) {
- if(typicalSpread === 0) {
- // edge case of no spread at all: fall back to max jitter
- maxJitterFactor = 1;
- jitterFactors = new Array(pts.length);
- for(i = 0; i < pts.length; i++) {
- jitterFactors[i] = 1;
- }
- } else {
- for(i = 0; i < pts.length; i++) {
- var i0 = Math.max(0, i - JITTERCOUNT);
- var pmin = pts[i0].v;
- var i1 = Math.min(pts.length - 1, i + JITTERCOUNT);
- var pmax = pts[i1].v;
-
- if(mode !== 'all') {
- if(pts[i].v < d.lf) pmax = Math.min(pmax, d.lf);
- else pmin = Math.max(pmin, d.uf);
- }
-
- var jitterFactor = Math.sqrt(spreadLimit * (i1 - i0) / (pmax - pmin + minSpread)) || 0;
- jitterFactor = Lib.constrain(Math.abs(jitterFactor), 0, 1);
-
- jitterFactors.push(jitterFactor);
- maxJitterFactor = Math.max(jitterFactor, maxJitterFactor);
- }
- }
- newJitter = trace.jitter * 2 / (maxJitterFactor || 1);
- }
-
- // fills in 'x' and 'y' in calcdata 'pts' item
- for(i = 0; i < pts.length; i++) {
- var pt = pts[i];
- var v = pt.v;
-
- var jitterOffset = trace.jitter ?
- (newJitter * jitterFactors[i] * (Lib.pseudoRandom() - 0.5)) :
- 0;
-
- var posPx = d.pos + bPos + bdPos * (trace.pointpos + jitterOffset);
-
- if(trace.orientation === 'h') {
- pt.y = posPx;
- pt.x = v;
- } else {
- pt.x = posPx;
- pt.y = v;
- }
-
- // tag suspected outliers
- if(mode === 'suspectedoutliers' && v < d.uo && v > d.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
- var mode = trace.boxmean || (trace.meanline || {}).visible;
-
- // to support for one-sided box
- var 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 posc = posAxis.c2p(d.pos + bPos, true) + bPosPxOffset;
- var pos0 = posAxis.c2p(d.pos + bPos - bdPos0, true) + bPosPxOffset;
- var pos1 = posAxis.c2p(d.pos + bPos + bdPos1, true) + 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":72,"../../lib":168,"d3":16}],291:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'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 < cd.length; i++) {
- for(j = 0; j < (cd[i].pts || []).length; j++) {
- // clear selection
- cd[i].pts[j].selected = 0;
- }
- }
- } else {
- for(i = 0; i < cd.length; i++) {
- for(j = 0; j < (cd[i].pts || []).length; j++) {
- var pt = cd[i].pts[j];
- var x = xa.c2p(pt.x);
- var y = ya.c2p(pt.y);
-
- if(selectionTester.contains([x, y], null, pt.i, searchInfo)) {
- selection.push({
- pointNumber: pt.i,
- x: xa.c2d(pt.x),
- y: ya.c2d(pt.y)
- });
- pt.selected = 1;
- } else {
- pt.selected = 0;
- }
- }
- }
- }
-
- return selection;
-};
-
-},{}],292:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var d3 = _dereq_('d3');
-var Color = _dereq_('../../components/color');
-var Drawing = _dereq_('../../components/drawing');
-
-function style(gd, cd) {
- var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.boxes');
-
- s.style('opacity', function(d) { return d[0].trace.opacity; });
-
- s.each(function(d) {
- var el = d3.select(this);
- var trace = d[0].trace;
- var lineWidth = trace.line.width;
-
- function styleBox(boxSel, lineWidth, lineColor, fillColor) {
- boxSel.style('stroke-width', lineWidth + 'px')
- .call(Color.stroke, lineColor)
- .call(Color.fill, fillColor);
- }
-
- var allBoxes = el.selectAll('path.box');
-
- if(trace.type === 'candlestick') {
- allBoxes.each(function(boxData) {
- if(boxData.empty) return;
-
- var thisBox = d3.select(this);
- var container = trace[boxData.dir]; // dir = 'increasing' or 'decreasing'
- styleBox(thisBox, container.line.width, container.line.color, container.fillcolor);
- // TODO: custom selection style for candlesticks
- thisBox.style('opacity', trace.selectedpoints && !boxData.selected ? 0.3 : 1);
- });
- } else {
- styleBox(allBoxes, lineWidth, trace.line.color, trace.fillcolor);
- el.selectAll('path.mean')
- .style({
- 'stroke-width': lineWidth,
- 'stroke-dasharray': (2 * lineWidth) + 'px,' + lineWidth + 'px'
- })
- .call(Color.stroke, trace.line.color);
-
- var pts = el.selectAll('path.point');
- Drawing.pointStyle(pts, trace, gd);
- }
- });
-}
-
-function styleOnSelect(gd, cd) {
- var s = cd[0].node3;
- var trace = cd[0].trace;
- var pts = s.selectAll('path.point');
-
- if(trace.selectedpoints) {
- Drawing.selectedPointStyle(pts, trace);
- } else {
- Drawing.pointStyle(pts, trace, gd);
- }
-}
-
-module.exports = {
- style: style,
- styleOnSelect: styleOnSelect
-};
-
-},{"../../components/color":51,"../../components/drawing":72,"d3":16}],293:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var heatmapAttrs = _dereq_('../heatmap/attributes');
-var scatterAttrs = _dereq_('../scatter/attributes');
-var colorScaleAttrs = _dereq_('../../components/colorscale/attributes');
-var dash = _dereq_('../../components/drawing/attributes').dash;
-var fontAttrs = _dereq_('../../plots/font_attributes');
-var extendFlat = _dereq_('../../lib/extend').extendFlat;
-
-var filterOps = _dereq_('../../constants/filter_ops');
-var COMPARISON_OPS2 = filterOps.COMPARISON_OPS2;
-var INTERVAL_OPS = filterOps.INTERVAL_OPS;
-
-var scatterLineAttrs = scatterAttrs.line;
-
-module.exports = extendFlat({
- z: heatmapAttrs.z,
- x: heatmapAttrs.x,
- x0: heatmapAttrs.x0,
- dx: heatmapAttrs.dx,
- y: heatmapAttrs.y,
- y0: heatmapAttrs.y0,
- dy: heatmapAttrs.dy,
- text: heatmapAttrs.text,
- hovertext: heatmapAttrs.hovertext,
- transpose: heatmapAttrs.transpose,
- xtype: heatmapAttrs.xtype,
- ytype: heatmapAttrs.ytype,
- zhoverformat: heatmapAttrs.zhoverformat,
- hovertemplate: heatmapAttrs.hovertemplate,
-
- connectgaps: heatmapAttrs.connectgaps,
-
- fillcolor: {
- valType: 'color',
-
- editType: 'calc',
-
- },
-
- autocontour: {
- valType: 'boolean',
- dflt: true,
-
- editType: 'calc',
- impliedEdits: {
- 'contours.start': undefined,
- 'contours.end': undefined,
- 'contours.size': undefined
- },
-
- },
- ncontours: {
- valType: 'integer',
- dflt: 15,
- min: 1,
-
- editType: 'calc',
-
- },
-
- contours: {
- type: {
- valType: 'enumerated',
- values: ['levels', 'constraint'],
- dflt: 'levels',
-
- editType: 'calc',
-
- },
- start: {
- valType: 'number',
- dflt: null,
-
- editType: 'plot',
- impliedEdits: {'^autocontour': false},
-
- },
- end: {
- valType: 'number',
- dflt: null,
-
- editType: 'plot',
- impliedEdits: {'^autocontour': false},
-
- },
- size: {
- valType: 'number',
- dflt: null,
- min: 0,
-
- editType: 'plot',
- impliedEdits: {'^autocontour': false},
-
- },
- coloring: {
- valType: 'enumerated',
- values: ['fill', 'heatmap', 'lines', 'none'],
- dflt: 'fill',
-
- editType: 'calc',
-
- },
- showlines: {
- valType: 'boolean',
- dflt: true,
-
- editType: 'plot',
-
- },
- showlabels: {
- valType: 'boolean',
- dflt: false,
-
- editType: 'plot',
-
- },
- labelfont: fontAttrs({
- editType: 'plot',
- colorEditType: 'style',
-
- }),
- labelformat: {
- valType: 'string',
- dflt: '',
-
- editType: 'plot',
-
- },
- operation: {
- valType: 'enumerated',
- values: [].concat(COMPARISON_OPS2).concat(INTERVAL_OPS),
-
- dflt: '=',
- editType: 'calc',
-
- },
- value: {
- valType: 'any',
- dflt: 0,
-
- editType: 'calc',
-
- },
- editType: 'calc',
- impliedEdits: {'autocontour': false}
- },
-
- line: {
- color: extendFlat({}, scatterLineAttrs.color, {
- editType: 'style+colorbars',
-
- }),
- width: extendFlat({}, scatterLineAttrs.width, {
- editType: 'style+colorbars'
- }),
- dash: dash,
- smoothing: extendFlat({}, scatterLineAttrs.smoothing, {
-
- }),
- editType: 'plot'
- }
-},
- colorScaleAttrs('', {
- cLetter: 'z',
- autoColorDflt: false,
- editTypeOverride: 'calc'
- })
-);
-
-},{"../../components/colorscale/attributes":58,"../../components/drawing/attributes":71,"../../constants/filter_ops":147,"../../lib/extend":162,"../../plots/font_attributes":238,"../heatmap/attributes":315,"../scatter/attributes":365}],294:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Colorscale = _dereq_('../../components/colorscale');
-
-var heatmapCalc = _dereq_('../heatmap/calc');
-var setContours = _dereq_('./set_contours');
-var endPlus = _dereq_('./end_plus');
-
-// most is the same as heatmap calc, then adjust it
-// though a few things inside heatmap calc still look for
-// contour maps, because the makeBoundArray calls are too entangled
-module.exports = function calc(gd, trace) {
- var cd = heatmapCalc(gd, trace);
-
- var zOut = cd[0].z;
- setContours(trace, zOut);
-
- var contours = trace.contours;
- var cOpts = Colorscale.extractOpts(trace);
- var cVals;
-
- if(contours.coloring === 'heatmap' && cOpts.auto && trace.autocontour === false) {
- var start = contours.start;
- var end = endPlus(contours);
- var cs = contours.size || 1;
- var nc = Math.floor((end - start) / cs) + 1;
-
- if(!isFinite(cs)) {
- cs = 1;
- nc = 1;
- }
-
- var min0 = start - cs / 2;
- var max0 = min0 + nc * cs;
- cVals = [min0, max0];
- } else {
- cVals = zOut;
- }
-
- Colorscale.calc(gd, trace, {vals: cVals, cLetter: 'z'});
-
- return cd;
-};
-
-},{"../../components/colorscale":63,"../heatmap/calc":316,"./end_plus":304,"./set_contours":312}],295:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = function(pathinfo, operation, perimeter, trace) {
- // Abandon all hope, ye who enter here.
- var i, v1, v2;
- var pi0 = pathinfo[0];
- var na = pi0.x.length;
- var nb = pi0.y.length;
- var z = pi0.z;
- var contours = trace.contours;
-
- var boundaryMax = -Infinity;
- var boundaryMin = Infinity;
-
- for(i = 0; i < nb; i++) {
- boundaryMin = Math.min(boundaryMin, z[i][0]);
- boundaryMin = Math.min(boundaryMin, z[i][na - 1]);
- boundaryMax = Math.max(boundaryMax, z[i][0]);
- boundaryMax = Math.max(boundaryMax, z[i][na - 1]);
- }
-
- for(i = 1; i < na - 1; i++) {
- boundaryMin = Math.min(boundaryMin, z[0][i]);
- boundaryMin = Math.min(boundaryMin, z[nb - 1][i]);
- boundaryMax = Math.max(boundaryMax, z[0][i]);
- boundaryMax = Math.max(boundaryMax, z[nb - 1][i]);
- }
-
- pi0.prefixBoundary = false;
-
- switch(operation) {
- case '>':
- if(contours.value > boundaryMax) {
- pi0.prefixBoundary = true;
- }
- break;
- case '<':
- if(contours.value < boundaryMin) {
- pi0.prefixBoundary = true;
- }
- break;
- case '[]':
- v1 = Math.min.apply(null, contours.value);
- v2 = Math.max.apply(null, contours.value);
- if(v2 < boundaryMin || v1 > boundaryMax) {
- pi0.prefixBoundary = true;
- }
- break;
- case '][':
- v1 = Math.min.apply(null, contours.value);
- v2 = Math.max.apply(null, contours.value);
- if(v1 < boundaryMin && v2 > boundaryMax) {
- pi0.prefixBoundary = true;
- }
- break;
- }
-};
-
-},{}],296:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var extractOpts = _dereq_('../../components/colorscale').extractOpts;
-var makeColorMap = _dereq_('./make_color_map');
-var endPlus = _dereq_('./end_plus');
-
-function calc(gd, trace, opts) {
- var contours = trace.contours;
- var line = trace.line;
- var cs = contours.size || 1;
- var coloring = contours.coloring;
- var colorMap = makeColorMap(trace, {isColorbar: true});
-
- if(coloring === 'heatmap') {
- var cOpts = extractOpts(trace);
- opts._fillgradient = trace.colorscale;
- opts._zrange = [cOpts.min, cOpts.max];
- } else if(coloring === 'fill') {
- opts._fillcolor = colorMap;
- }
-
- opts._line = {
- color: coloring === 'lines' ? colorMap : line.color,
- width: contours.showlines !== false ? line.width : 0,
- dash: line.dash
- };
-
- opts._levels = {
- start: contours.start,
- end: endPlus(contours),
- size: cs
- };
-}
-
-module.exports = {
- min: 'zmin',
- max: 'zmax',
- calc: calc
-};
-
-},{"../../components/colorscale":63,"./end_plus":304,"./make_color_map":309}],297:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-module.exports = {
- // some constants to help with marching squares algorithm
- // where does the path start for each index?
- BOTTOMSTART: [1, 9, 13, 104, 713],
- TOPSTART: [4, 6, 7, 104, 713],
- LEFTSTART: [8, 12, 14, 208, 1114],
- RIGHTSTART: [2, 3, 11, 208, 1114],
-
- // which way [dx,dy] do we leave a given index?
- // saddles are already disambiguated
- NEWDELTA: [
- null, [-1, 0], [0, -1], [-1, 0],
- [1, 0], null, [0, -1], [-1, 0],
- [0, 1], [0, 1], null, [0, 1],
- [1, 0], [1, 0], [0, -1]
- ],
-
- // for each saddle, the first index here is used
- // for dx||dy<0, the second for dx||dy>0
- CHOOSESADDLE: {
- 104: [4, 1],
- 208: [2, 8],
- 713: [7, 13],
- 1114: [11, 14]
- },
-
- // after one index has been used for a saddle, which do we
- // substitute to be used up later?
- SADDLEREMAINDER: {1: 4, 2: 8, 4: 1, 7: 13, 8: 2, 11: 14, 13: 7, 14: 11},
-
- // length of a contour, as a multiple of the plot area diagonal, per label
- LABELDISTANCE: 2,
-
- // number of contour levels after which we start increasing the number of
- // labels we draw. Many contours means they will generally be close
- // together, so it will be harder to follow a long way to find a label
- LABELINCREASE: 10,
-
- // minimum length of a contour line, as a multiple of the label length,
- // at which we draw *any* labels
- LABELMIN: 3,
-
- // max number of labels to draw on a single contour path, no matter how long
- LABELMAX: 10,
-
- // constants for the label position cost function
- LABELOPTIMIZER: {
- // weight given to edge proximity
- EDGECOST: 1,
- // weight given to the angle off horizontal
- ANGLECOST: 1,
- // weight given to distance from already-placed labels
- NEIGHBORCOST: 5,
- // cost multiplier for labels on the same level
- SAMELEVELFACTOR: 10,
- // minimum distance (as a multiple of the label length)
- // for labels on the same level
- SAMELEVELDISTANCE: 5,
- // maximum cost before we won't even place the label
- MAXCOST: 100,
- // number of evenly spaced points to look at in the first
- // iteration of the search
- INITIALSEARCHPOINTS: 10,
- // number of binary search iterations after the initial wide search
- ITERATIONS: 5
- }
-};
-
-},{}],298:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-var isNumeric = _dereq_('fast-isnumeric');
-
-var handleLabelDefaults = _dereq_('./label_defaults');
-
-var Color = _dereq_('../../components/color');
-var addOpacity = Color.addOpacity;
-var opacity = Color.opacity;
-
-var filterOps = _dereq_('../../constants/filter_ops');
-var CONSTRAINT_REDUCTION = filterOps.CONSTRAINT_REDUCTION;
-var COMPARISON_OPS2 = filterOps.COMPARISON_OPS2;
-
-module.exports = function handleConstraintDefaults(traceIn, traceOut, coerce, layout, defaultColor, opts) {
- var contours = traceOut.contours;
- var showLines, lineColor, fillColor;
-
- var operation = coerce('contours.operation');
- contours._operation = CONSTRAINT_REDUCTION[operation];
-
- handleConstraintValueDefaults(coerce, contours);
-
- if(operation === '=') {
- showLines = contours.showlines = true;
- } else {
- showLines = coerce('contours.showlines');
- fillColor = coerce('fillcolor', addOpacity(
- (traceIn.line || {}).color || defaultColor, 0.5
- ));
- }
-
- if(showLines) {
- var lineDfltColor = fillColor && opacity(fillColor) ?
- addOpacity(traceOut.fillcolor, 1) :
- defaultColor;
- lineColor = coerce('line.color', lineDfltColor);
- coerce('line.width', 2);
- coerce('line.dash');
- }
-
- coerce('line.smoothing');
-
- handleLabelDefaults(coerce, layout, lineColor, opts);
-};
-
-function handleConstraintValueDefaults(coerce, contours) {
- var zvalue;
-
- if(COMPARISON_OPS2.indexOf(contours.operation) === -1) {
- // Requires an array of two numbers:
- coerce('contours.value', [0, 1]);
-
- if(!Array.isArray(contours.value)) {
- if(isNumeric(contours.value)) {
- zvalue = parseFloat(contours.value);
- contours.value = [zvalue, zvalue + 1];
- }
- } else if(contours.value.length > 2) {
- contours.value = contours.value.slice(2);
- } else if(contours.length === 0) {
- contours.value = [0, 1];
- } else if(contours.length < 2) {
- zvalue = parseFloat(contours.value[0]);
- contours.value = [zvalue, zvalue + 1];
- } else {
- contours.value = [
- parseFloat(contours.value[0]),
- parseFloat(contours.value[1])
- ];
- }
- } else {
- // Requires a single scalar:
- coerce('contours.value', 0);
-
- if(!isNumeric(contours.value)) {
- if(Array.isArray(contours.value)) {
- contours.value = parseFloat(contours.value[0]);
- } else {
- contours.value = 0;
- }
- }
- }
-}
-
-},{"../../components/color":51,"../../constants/filter_ops":147,"./label_defaults":308,"fast-isnumeric":18}],299:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var filterOps = _dereq_('../../constants/filter_ops');
-var isNumeric = _dereq_('fast-isnumeric');
-
-// This syntax conforms to the existing filter transform syntax, but we don't care
-// about open vs. closed intervals for simply drawing contours constraints:
-module.exports = {
- '[]': makeRangeSettings('[]'),
- '][': makeRangeSettings(']['),
- '>': makeInequalitySettings('>'),
- '<': makeInequalitySettings('<'),
- '=': makeInequalitySettings('=')
-};
-
-// This does not in any way shape or form support calendars. It's adapted from
-// transforms/filter.js.
-function coerceValue(operation, value) {
- var hasArrayValue = Array.isArray(value);
-
- var coercedValue;
-
- function coerce(value) {
- return isNumeric(value) ? (+value) : null;
- }
-
- if(filterOps.COMPARISON_OPS2.indexOf(operation) !== -1) {
- coercedValue = hasArrayValue ? coerce(value[0]) : coerce(value);
- } else if(filterOps.INTERVAL_OPS.indexOf(operation) !== -1) {
- coercedValue = hasArrayValue ?
- [coerce(value[0]), coerce(value[1])] :
- [coerce(value), coerce(value)];
- } else if(filterOps.SET_OPS.indexOf(operation) !== -1) {
- coercedValue = hasArrayValue ? value.map(coerce) : [coerce(value)];
- }
-
- return coercedValue;
-}
-
-// Returns a parabola scaled so that the min/max is either +/- 1 and zero at the two values
-// provided. The data is mapped by this function when constructing intervals so that it's
-// very easy to construct contours as normal.
-function makeRangeSettings(operation) {
- return function(value) {
- value = coerceValue(operation, value);
-
- // Ensure proper ordering:
- var min = Math.min(value[0], value[1]);
- var max = Math.max(value[0], value[1]);
-
- return {
- start: min,
- end: max,
- size: max - min
- };
- };
-}
-
-function makeInequalitySettings(operation) {
- return function(value) {
- value = coerceValue(operation, value);
-
- return {
- start: value,
- end: Infinity,
- size: Infinity
- };
- };
-}
-
-},{"../../constants/filter_ops":147,"fast-isnumeric":18}],300:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = function handleContourDefaults(traceIn, traceOut, coerce, coerce2) {
- var contourStart = coerce2('contours.start');
- var contourEnd = coerce2('contours.end');
- var missingEnd = (contourStart === false) || (contourEnd === false);
-
- // normally we only need size if autocontour is off. But contour.calc
- // pushes its calculated contour size back to the input trace, so for
- // things like restyle that can call supplyDefaults without calc
- // after the initial draw, we can just reuse the previous calculation
- var contourSize = coerce('contours.size');
- var autoContour;
-
- if(missingEnd) autoContour = traceOut.autocontour = true;
- else autoContour = coerce('autocontour', false);
-
- if(autoContour || !contourSize) coerce('ncontours');
-};
-
-},{}],301:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-// The contour extraction is great, except it totally fails for constraints because we
-// need weird range loops and flipped contours instead of the usual format. This function
-// does some weird manipulation of the extracted pathinfo data such that it magically
-// draws contours correctly *as* constraints.
-module.exports = function(pathinfo, operation) {
- var i, pi0, pi1;
-
- var op0 = function(arr) { return arr.reverse(); };
- var op1 = function(arr) { return arr; };
-
- switch(operation) {
- case '=':
- case '<':
- return pathinfo;
- case '>':
- if(pathinfo.length !== 1) {
- Lib.warn('Contour data invalid for the specified inequality operation.');
- }
-
- // In this case there should be exactly two contour levels in pathinfo. We
- // simply concatenate the info into one pathinfo and flip all of the data
- // in one. This will draw the contour as closed.
- pi0 = pathinfo[0];
-
- for(i = 0; i < pi0.edgepaths.length; i++) {
- pi0.edgepaths[i] = op0(pi0.edgepaths[i]);
- }
-
- for(i = 0; i < pi0.paths.length; i++) {
- pi0.paths[i] = op0(pi0.paths[i]);
- }
- return pathinfo;
- case '][':
- var tmp = op0;
- op0 = op1;
- op1 = tmp;
- // It's a nice rule, except this definitely *is* what's intended here.
- /* eslint-disable: no-fallthrough */
- case '[]':
- /* eslint-enable: no-fallthrough */
- if(pathinfo.length !== 2) {
- Lib.warn('Contour data invalid for the specified inequality range operation.');
- }
-
- // In this case there should be exactly two contour levels in pathinfo. We
- // simply concatenate the info into one pathinfo and flip all of the data
- // in one. This will draw the contour as closed.
- pi0 = copyPathinfo(pathinfo[0]);
- pi1 = copyPathinfo(pathinfo[1]);
-
- for(i = 0; i < pi0.edgepaths.length; i++) {
- pi0.edgepaths[i] = op0(pi0.edgepaths[i]);
- }
-
- for(i = 0; i < pi0.paths.length; i++) {
- pi0.paths[i] = op0(pi0.paths[i]);
- }
-
- while(pi1.edgepaths.length) {
- pi0.edgepaths.push(op1(pi1.edgepaths.shift()));
- }
- while(pi1.paths.length) {
- pi0.paths.push(op1(pi1.paths.shift()));
- }
- return [pi0];
- }
-};
-
-function copyPathinfo(pi) {
- return Lib.extendFlat({}, pi, {
- edgepaths: Lib.extendDeep([], pi.edgepaths),
- paths: Lib.extendDeep([], pi.paths)
- });
-}
-
-},{"../../lib":168}],302:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-var handleXYZDefaults = _dereq_('../heatmap/xyz_defaults');
-var handleConstraintDefaults = _dereq_('./constraint_defaults');
-var handleContoursDefaults = _dereq_('./contours_defaults');
-var handleStyleDefaults = _dereq_('./style_defaults');
-var attributes = _dereq_('./attributes');
-
-
-module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
- function coerce(attr, dflt) {
- return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
- }
-
- function coerce2(attr) {
- return Lib.coerce2(traceIn, traceOut, attributes, attr);
- }
-
- var len = handleXYZDefaults(traceIn, traceOut, coerce, layout);
- if(!len) {
- traceOut.visible = false;
- return;
- }
-
- coerce('text');
- coerce('hovertext');
- coerce('hovertemplate');
-
- var isConstraint = (coerce('contours.type') === 'constraint');
- coerce('connectgaps', Lib.isArray1D(traceOut.z));
-
- if(isConstraint) {
- handleConstraintDefaults(traceIn, traceOut, coerce, layout, defaultColor);
- } else {
- handleContoursDefaults(traceIn, traceOut, coerce, coerce2);
- handleStyleDefaults(traceIn, traceOut, coerce, layout);
- }
-};
-
-},{"../../lib":168,"../heatmap/xyz_defaults":329,"./attributes":293,"./constraint_defaults":298,"./contours_defaults":300,"./style_defaults":314}],303:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var constraintMapping = _dereq_('./constraint_mapping');
-var endPlus = _dereq_('./end_plus');
-
-module.exports = function emptyPathinfo(contours, plotinfo, cd0) {
- var contoursFinal = (contours.type === 'constraint') ?
- constraintMapping[contours._operation](contours.value) :
- contours;
-
- var cs = contoursFinal.size;
- var pathinfo = [];
- var end = endPlus(contoursFinal);
-
- var carpet = cd0.trace._carpetTrace;
-
- var basePathinfo = carpet ? {
- // store axes so we can convert to px
- xaxis: carpet.aaxis,
- yaxis: carpet.baxis,
- // full data arrays to use for interpolation
- x: cd0.a,
- y: cd0.b
- } : {
- xaxis: plotinfo.xaxis,
- yaxis: plotinfo.yaxis,
- x: cd0.x,
- y: cd0.y
- };
-
- for(var ci = contoursFinal.start; ci < end; ci += cs) {
- pathinfo.push(Lib.extendFlat({
- level: ci,
- // all the cells with nontrivial marching index
- crossings: {},
- // starting points on the edges of the lattice for each contour
- starts: [],
- // all unclosed paths (may have less items than starts,
- // if a path is closed by rounding)
- edgepaths: [],
- // all closed paths
- paths: [],
- z: cd0.z,
- smoothing: cd0.trace.line.smoothing
- }, basePathinfo));
-
- if(pathinfo.length > 1000) {
- Lib.warn('Too many contours, clipping at 1000', contours);
- break;
- }
- }
- return pathinfo;
-};
-
-},{"../../lib":168,"./constraint_mapping":299,"./end_plus":304}],304:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-/*
- * tiny helper to move the end of the contours a little to prevent
- * losing the last contour to rounding errors
- */
-module.exports = function endPlus(contours) {
- return contours.end + contours.size / 1e6;
-};
-
-},{}],305:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var constants = _dereq_('./constants');
-
-module.exports = function findAllPaths(pathinfo, xtol, ytol) {
- var cnt,
- startLoc,
- i,
- pi,
- j;
-
- // Default just passes these values through as they were before:
- xtol = xtol || 0.01;
- ytol = ytol || 0.01;
-
- for(i = 0; i < pathinfo.length; i++) {
- pi = pathinfo[i];
-
- for(j = 0; j < pi.starts.length; j++) {
- startLoc = pi.starts[j];
- makePath(pi, startLoc, 'edge', xtol, ytol);
- }
-
- cnt = 0;
- while(Object.keys(pi.crossings).length && cnt < 10000) {
- cnt++;
- startLoc = Object.keys(pi.crossings)[0].split(',').map(Number);
- makePath(pi, startLoc, undefined, xtol, ytol);
- }
- if(cnt === 10000) Lib.log('Infinite loop in contour?');
- }
-};
-
-function equalPts(pt1, pt2, xtol, ytol) {
- return Math.abs(pt1[0] - pt2[0]) < xtol &&
- Math.abs(pt1[1] - pt2[1]) < ytol;
-}
-
-// distance in index units - uses the 3rd and 4th items in points
-function ptDist(pt1, pt2) {
- var dx = pt1[2] - pt2[2];
- var dy = pt1[3] - pt2[3];
- return Math.sqrt(dx * dx + dy * dy);
-}
-
-function makePath(pi, loc, edgeflag, xtol, ytol) {
- var startLocStr = loc.join(',');
- var locStr = startLocStr;
- var mi = pi.crossings[locStr];
- var marchStep = startStep(mi, edgeflag, loc);
- // start by going backward a half step and finding the crossing point
- var pts = [getInterpPx(pi, loc, [-marchStep[0], -marchStep[1]])];
- var startStepStr = marchStep.join(',');
- var m = pi.z.length;
- var n = pi.z[0].length;
- var cnt;
-
- // now follow the path
- for(cnt = 0; cnt < 10000; cnt++) { // just to avoid infinite loops
- if(mi > 20) {
- mi = constants.CHOOSESADDLE[mi][(marchStep[0] || marchStep[1]) < 0 ? 0 : 1];
- pi.crossings[locStr] = constants.SADDLEREMAINDER[mi];
- } else {
- delete pi.crossings[locStr];
- }
-
- marchStep = constants.NEWDELTA[mi];
- if(!marchStep) {
- Lib.log('Found bad marching index:', mi, loc, pi.level);
- break;
- }
-
- // find the crossing a half step forward, and then take the full step
- pts.push(getInterpPx(pi, loc, marchStep));
- loc[0] += marchStep[0];
- loc[1] += marchStep[1];
-
- // don't include the same point multiple times
- if(equalPts(pts[pts.length - 1], pts[pts.length - 2], xtol, ytol)) pts.pop();
- locStr = loc.join(',');
-
- var atEdge = (marchStep[0] && (loc[0] < 0 || loc[0] > n - 2)) ||
- (marchStep[1] && (loc[1] < 0 || loc[1] > m - 2));
- var closedLoop = (locStr === startLocStr) && (marchStep.join(',') === startStepStr);
-
- // have we completed a loop, or reached an edge?
- if((closedLoop) || (edgeflag && atEdge)) break;
-
- mi = pi.crossings[locStr];
- }
-
- if(cnt === 10000) {
- Lib.log('Infinite loop in contour?');
- }
- var closedpath = equalPts(pts[0], pts[pts.length - 1], xtol, ytol);
- var totaldist = 0;
- var distThresholdFactor = 0.2 * pi.smoothing;
- var alldists = [];
- var cropstart = 0;
- var distgroup, cnt2, cnt3, newpt, ptcnt, ptavg, thisdist,
- i, j, edgepathi, edgepathj;
-
- /*
- * Check for points that are too close together (<1/5 the average dist
- * *in grid index units* (important for log axes and nonuniform grids),
- * less if less smoothed) and just take the center (or avg of center 2).
- * This cuts down on funny behavior when a point is very close to a
- * contour level.
- */
- for(cnt = 1; cnt < pts.length; cnt++) {
- thisdist = ptDist(pts[cnt], pts[cnt - 1]);
- totaldist += thisdist;
- alldists.push(thisdist);
- }
-
- var distThreshold = totaldist / alldists.length * distThresholdFactor;
-
- function getpt(i) { return pts[i % pts.length]; }
-
- for(cnt = pts.length - 2; cnt >= cropstart; cnt--) {
- distgroup = alldists[cnt];
- if(distgroup < distThreshold) {
- cnt3 = 0;
- for(cnt2 = cnt - 1; cnt2 >= cropstart; cnt2--) {
- if(distgroup + alldists[cnt2] < distThreshold) {
- distgroup += alldists[cnt2];
- } else break;
- }
-
- // closed path with close points wrapping around the boundary?
- if(closedpath && cnt === pts.length - 2) {
- for(cnt3 = 0; cnt3 < cnt2; cnt3++) {
- if(distgroup + alldists[cnt3] < distThreshold) {
- distgroup += alldists[cnt3];
- } else break;
- }
- }
- ptcnt = cnt - cnt2 + cnt3 + 1;
- ptavg = Math.floor((cnt + cnt2 + cnt3 + 2) / 2);
-
- // either endpoint included: keep the endpoint
- if(!closedpath && cnt === pts.length - 2) newpt = pts[pts.length - 1];
- else if(!closedpath && cnt2 === -1) newpt = pts[0];
-
- // odd # of points - just take the central one
- else if(ptcnt % 2) newpt = getpt(ptavg);
-
- // even # of pts - average central two
- else {
- newpt = [(getpt(ptavg)[0] + getpt(ptavg + 1)[0]) / 2,
- (getpt(ptavg)[1] + getpt(ptavg + 1)[1]) / 2];
- }
-
- pts.splice(cnt2 + 1, cnt - cnt2 + 1, newpt);
- cnt = cnt2 + 1;
- if(cnt3) cropstart = cnt3;
- if(closedpath) {
- if(cnt === pts.length - 2) pts[cnt3] = pts[pts.length - 1];
- else if(cnt === 0) pts[pts.length - 1] = pts[0];
- }
- }
- }
- pts.splice(0, cropstart);
-
- // done with the index parts - remove them so path generation works right
- // because it depends on only having [xpx, ypx]
- for(cnt = 0; cnt < pts.length; cnt++) pts[cnt].length = 2;
-
- // don't return single-point paths (ie all points were the same
- // so they got deleted?)
- if(pts.length < 2) return;
- else if(closedpath) {
- pts.pop();
- pi.paths.push(pts);
- } else {
- if(!edgeflag) {
- Lib.log('Unclosed interior contour?',
- pi.level, startLocStr, pts.join('L'));
- }
-
- // edge path - does it start where an existing edge path ends, or vice versa?
- var merged = false;
- for(i = 0; i < pi.edgepaths.length; i++) {
- edgepathi = pi.edgepaths[i];
- if(!merged && equalPts(edgepathi[0], pts[pts.length - 1], xtol, ytol)) {
- pts.pop();
- merged = true;
-
- // now does it ALSO meet the end of another (or the same) path?
- var doublemerged = false;
- for(j = 0; j < pi.edgepaths.length; j++) {
- edgepathj = pi.edgepaths[j];
- if(equalPts(edgepathj[edgepathj.length - 1], pts[0], xtol, ytol)) {
- doublemerged = true;
- pts.shift();
- pi.edgepaths.splice(i, 1);
- if(j === i) {
- // the path is now closed
- pi.paths.push(pts.concat(edgepathj));
- } else {
- if(j > i) j--;
- pi.edgepaths[j] = edgepathj.concat(pts, edgepathi);
- }
- break;
- }
- }
- if(!doublemerged) {
- pi.edgepaths[i] = pts.concat(edgepathi);
- }
- }
- }
- for(i = 0; i < pi.edgepaths.length; i++) {
- if(merged) break;
- edgepathi = pi.edgepaths[i];
- if(equalPts(edgepathi[edgepathi.length - 1], pts[0], xtol, ytol)) {
- pts.shift();
- pi.edgepaths[i] = edgepathi.concat(pts);
- merged = true;
- }
- }
-
- if(!merged) pi.edgepaths.push(pts);
- }
-}
-
-// special function to get the marching step of the
-// first point in the path (leading to loc)
-function startStep(mi, edgeflag, loc) {
- var dx = 0;
- var dy = 0;
- if(mi > 20 && edgeflag) {
- // these saddles start at +/- x
- if(mi === 208 || mi === 1114) {
- // if we're starting at the left side, we must be going right
- dx = loc[0] === 0 ? 1 : -1;
- } else {
- // if we're starting at the bottom, we must be going up
- dy = loc[1] === 0 ? 1 : -1;
- }
- } else if(constants.BOTTOMSTART.indexOf(mi) !== -1) dy = 1;
- else if(constants.LEFTSTART.indexOf(mi) !== -1) dx = 1;
- else if(constants.TOPSTART.indexOf(mi) !== -1) dy = -1;
- else dx = -1;
- return [dx, dy];
-}
-
-/*
- * Find the pixel coordinates of a particular crossing
- *
- * @param {object} pi: the pathinfo object at this level
- * @param {array} loc: the grid index [x, y] of the crossing
- * @param {array} step: the direction [dx, dy] we're moving on the grid
- *
- * @return {array} [xpx, ypx, xi, yi]: the first two are the pixel location,
- * the next two are the interpolated grid indices, which we use for
- * distance calculations to delete points that are too close together.
- * This is important when the grid is nonuniform (and most dramatically when
- * we're on log axes and include invalid (0 or negative) values.
- * It's crucial to delete these extra two before turning an array of these
- * points into a path, because those routines require length-2 points.
- */
-function getInterpPx(pi, loc, step) {
- var locx = loc[0] + Math.max(step[0], 0);
- var locy = loc[1] + Math.max(step[1], 0);
- var zxy = pi.z[locy][locx];
- var xa = pi.xaxis;
- var ya = pi.yaxis;
-
- if(step[1]) {
- var dx = (pi.level - zxy) / (pi.z[locy][locx + 1] - zxy);
-
- return [xa.c2p((1 - dx) * pi.x[locx] + dx * pi.x[locx + 1], true),
- ya.c2p(pi.y[locy], true),
- locx + dx, locy];
- } else {
- var dy = (pi.level - zxy) / (pi.z[locy + 1][locx] - zxy);
- return [xa.c2p(pi.x[locx], true),
- ya.c2p((1 - dy) * pi.y[locy] + dy * pi.y[locy + 1], true),
- locx, locy + dy];
- }
-}
-
-},{"../../lib":168,"./constants":297}],306:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var Color = _dereq_('../../components/color');
-
-var heatmapHoverPoints = _dereq_('../heatmap/hover');
-
-module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLayer) {
- var hoverData = heatmapHoverPoints(pointData, xval, yval, hovermode, hoverLayer, true);
-
- if(hoverData) {
- hoverData.forEach(function(hoverPt) {
- var trace = hoverPt.trace;
- if(trace.contours.type === 'constraint') {
- if(trace.fillcolor && Color.opacity(trace.fillcolor)) {
- hoverPt.color = Color.addOpacity(trace.fillcolor, 1);
- } else if(trace.contours.showlines && Color.opacity(trace.line.color)) {
- hoverPt.color = Color.addOpacity(trace.line.color, 1);
- }
- }
- });
- }
-
- return hoverData;
-};
-
-},{"../../components/color":51,"../heatmap/hover":322}],307:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = {
- attributes: _dereq_('./attributes'),
- supplyDefaults: _dereq_('./defaults'),
- calc: _dereq_('./calc'),
- plot: _dereq_('./plot').plot,
- style: _dereq_('./style'),
- colorbar: _dereq_('./colorbar'),
- hoverPoints: _dereq_('./hover'),
-
- moduleType: 'trace',
- name: 'contour',
- basePlotModule: _dereq_('../../plots/cartesian'),
- categories: ['cartesian', 'svg', '2dMap', 'contour', 'showLegend'],
- meta: {
-
- }
-};
-
-},{"../../plots/cartesian":223,"./attributes":293,"./calc":294,"./colorbar":296,"./defaults":302,"./hover":306,"./plot":311,"./style":313}],308:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-module.exports = function handleLabelDefaults(coerce, layout, lineColor, opts) {
- if(!opts) opts = {};
- var showLabels = coerce('contours.showlabels');
- if(showLabels) {
- var globalFont = layout.font;
- Lib.coerceFont(coerce, 'contours.labelfont', {
- family: globalFont.family,
- size: globalFont.size,
- color: lineColor
- });
- coerce('contours.labelformat');
- }
-
- if(opts.hasHover !== false) coerce('zhoverformat');
-};
-
-},{"../../lib":168}],309:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var d3 = _dereq_('d3');
-
-var Colorscale = _dereq_('../../components/colorscale');
-var endPlus = _dereq_('./end_plus');
-
-module.exports = function makeColorMap(trace) {
- var contours = trace.contours;
- var start = contours.start;
- var end = endPlus(contours);
- var cs = contours.size || 1;
- var nc = Math.floor((end - start) / cs) + 1;
- var extra = contours.coloring === 'lines' ? 0 : 1;
- var cOpts = Colorscale.extractOpts(trace);
-
- if(!isFinite(cs)) {
- cs = 1;
- nc = 1;
- }
-
- var scl = cOpts.reversescale ?
- Colorscale.flipScale(cOpts.colorscale) :
- cOpts.colorscale;
-
- var len = scl.length;
- var domain = new Array(len);
- var range = new Array(len);
-
- var si, i;
-
- if(contours.coloring === 'heatmap') {
- var zmin0 = cOpts.min;
- var zmax0 = cOpts.max;
-
- for(i = 0; i < len; i++) {
- si = scl[i];
- domain[i] = si[0] * (zmax0 - zmin0) + zmin0;
- range[i] = si[1];
- }
-
- // do the contours extend beyond the colorscale?
- // if so, extend the colorscale with constants
- var zRange = d3.extent([
- zmin0,
- zmax0,
- contours.start,
- contours.start + cs * (nc - 1)
- ]);
- var zmin = zRange[zmin0 < zmax0 ? 0 : 1];
- var zmax = zRange[zmin0 < zmax0 ? 1 : 0];
-
- if(zmin !== zmin0) {
- domain.splice(0, 0, zmin);
- range.splice(0, 0, range[0]);
- }
-
- if(zmax !== zmax0) {
- domain.push(zmax);
- range.push(range[range.length - 1]);
- }
- } else {
- for(i = 0; i < len; i++) {
- si = scl[i];
- domain[i] = (si[0] * (nc + extra - 1) - (extra / 2)) * cs + start;
- range[i] = si[1];
- }
- }
-
- return Colorscale.makeColorScaleFunc(
- {domain: domain, range: range},
- {noNumericCheck: true}
- );
-};
-
-},{"../../components/colorscale":63,"./end_plus":304,"d3":16}],310:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var constants = _dereq_('./constants');
-
-// Calculate all the marching indices, for ALL levels at once.
-// since we want to be exhaustive we'll check for contour crossings
-// at every intersection, rather than just following a path
-// TODO: shorten the inner loop to only the relevant levels
-module.exports = function makeCrossings(pathinfo) {
- var z = pathinfo[0].z;
- var m = z.length;
- var n = z[0].length; // we already made sure z isn't ragged in interp2d
- var twoWide = m === 2 || n === 2;
- var xi;
- var yi;
- var startIndices;
- var ystartIndices;
- var label;
- var corners;
- var mi;
- var pi;
- var i;
-
- for(yi = 0; yi < m - 1; yi++) {
- ystartIndices = [];
- if(yi === 0) ystartIndices = ystartIndices.concat(constants.BOTTOMSTART);
- if(yi === m - 2) ystartIndices = ystartIndices.concat(constants.TOPSTART);
-
- for(xi = 0; xi < n - 1; xi++) {
- startIndices = ystartIndices.slice();
- if(xi === 0) startIndices = startIndices.concat(constants.LEFTSTART);
- if(xi === n - 2) startIndices = startIndices.concat(constants.RIGHTSTART);
-
- label = xi + ',' + yi;
- corners = [[z[yi][xi], z[yi][xi + 1]],
- [z[yi + 1][xi], z[yi + 1][xi + 1]]];
- for(i = 0; i < pathinfo.length; i++) {
- pi = pathinfo[i];
- mi = getMarchingIndex(pi.level, corners);
- if(!mi) continue;
-
- pi.crossings[label] = mi;
- if(startIndices.indexOf(mi) !== -1) {
- pi.starts.push([xi, yi]);
- if(twoWide && startIndices.indexOf(mi,
- startIndices.indexOf(mi) + 1) !== -1) {
- // the same square has starts from opposite sides
- // it's not possible to have starts on opposite edges
- // of a corner, only a start and an end...
- // but if the array is only two points wide (either way)
- // you can have starts on opposite sides.
- pi.starts.push([xi, yi]);
- }
- }
- }
- }
- }
-};
-
-// modified marching squares algorithm,
-// so we disambiguate the saddle points from the start
-// and we ignore the cases with no crossings
-// the index I'm using is based on:
-// http://en.wikipedia.org/wiki/Marching_squares
-// except that the saddles bifurcate and I represent them
-// as the decimal combination of the two appropriate
-// non-saddle indices
-function getMarchingIndex(val, corners) {
- var mi = (corners[0][0] > val ? 0 : 1) +
- (corners[0][1] > val ? 0 : 2) +
- (corners[1][1] > val ? 0 : 4) +
- (corners[1][0] > val ? 0 : 8);
- if(mi === 5 || mi === 10) {
- var avg = (corners[0][0] + corners[0][1] +
- corners[1][0] + corners[1][1]) / 4;
- // two peaks with a big valley
- if(val > avg) return (mi === 5) ? 713 : 1114;
- // two valleys with a big ridge
- return (mi === 5) ? 104 : 208;
- }
- return (mi === 15) ? 0 : mi;
-}
-
-},{"./constants":297}],311:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var d3 = _dereq_('d3');
-
-var Lib = _dereq_('../../lib');
-var Drawing = _dereq_('../../components/drawing');
-var svgTextUtils = _dereq_('../../lib/svg_text_utils');
-var Axes = _dereq_('../../plots/cartesian/axes');
-var setConvert = _dereq_('../../plots/cartesian/set_convert');
-
-var heatmapPlot = _dereq_('../heatmap/plot');
-var makeCrossings = _dereq_('./make_crossings');
-var findAllPaths = _dereq_('./find_all_paths');
-var emptyPathinfo = _dereq_('./empty_pathinfo');
-var convertToConstraints = _dereq_('./convert_to_constraints');
-var closeBoundaries = _dereq_('./close_boundaries');
-var constants = _dereq_('./constants');
-var costConstants = constants.LABELOPTIMIZER;
-
-exports.plot = function plot(gd, plotinfo, cdcontours, contourLayer) {
- var xa = plotinfo.xaxis;
- var ya = plotinfo.yaxis;
-
- Lib.makeTraceGroups(contourLayer, cdcontours, 'contour').each(function(cd) {
- var plotGroup = d3.select(this);
- var cd0 = cd[0];
- var trace = cd0.trace;
- var x = cd0.x;
- var y = cd0.y;
- var contours = trace.contours;
- var pathinfo = emptyPathinfo(contours, plotinfo, cd0);
-
- // use a heatmap to fill - draw it behind the lines
- var heatmapColoringLayer = Lib.ensureSingle(plotGroup, 'g', 'heatmapcoloring');
- var cdheatmaps = [];
- if(contours.coloring === 'heatmap') {
- cdheatmaps = [cd];
- }
- heatmapPlot(gd, plotinfo, cdheatmaps, heatmapColoringLayer);
-
- makeCrossings(pathinfo);
- findAllPaths(pathinfo);
-
- var leftedge = xa.c2p(x[0], true);
- var rightedge = xa.c2p(x[x.length - 1], true);
- var bottomedge = ya.c2p(y[0], true);
- var topedge = ya.c2p(y[y.length - 1], true);
- var perimeter = [
- [leftedge, topedge],
- [rightedge, topedge],
- [rightedge, bottomedge],
- [leftedge, bottomedge]
- ];
-
- var fillPathinfo = pathinfo;
- if(contours.type === 'constraint') {
- fillPathinfo = convertToConstraints(pathinfo, contours._operation);
- closeBoundaries(fillPathinfo, contours._operation, perimeter, trace);
- }
-
- // draw everything
- makeBackground(plotGroup, perimeter, contours);
- makeFills(plotGroup, fillPathinfo, perimeter, contours);
- makeLinesAndLabels(plotGroup, pathinfo, gd, cd0, contours);
- clipGaps(plotGroup, plotinfo, gd, cd0, perimeter);
- });
-};
-
-function makeBackground(plotgroup, perimeter, contours) {
- var bggroup = Lib.ensureSingle(plotgroup, 'g', 'contourbg');
-
- var bgfill = bggroup.selectAll('path')
- .data(contours.coloring === 'fill' ? [0] : []);
- bgfill.enter().append('path');
- bgfill.exit().remove();
- bgfill
- .attr('d', 'M' + perimeter.join('L') + 'Z')
- .style('stroke', 'none');
-}
-
-function makeFills(plotgroup, pathinfo, perimeter, contours) {
- var fillgroup = Lib.ensureSingle(plotgroup, 'g', 'contourfill');
-
- var fillitems = fillgroup.selectAll('path')
- .data(contours.coloring === 'fill' || (contours.type === 'constraint' && contours._operation !== '=') ? pathinfo : []);
- fillitems.enter().append('path');
- fillitems.exit().remove();
- fillitems.each(function(pi) {
- // join all paths for this level together into a single path
- // first follow clockwise around the perimeter to close any open paths
- // if the whole perimeter is above this level, start with a path
- // enclosing the whole thing. With all that, the parity should mean
- // that we always fill everything above the contour, nothing below
- var fullpath = joinAllPaths(pi, perimeter);
-
- if(!fullpath) d3.select(this).remove();
- else d3.select(this).attr('d', fullpath).style('stroke', 'none');
- });
-}
-
-function initFullPath(pi, perimeter) {
- var prefixBoundary = pi.prefixBoundary;
- if(prefixBoundary === undefined) {
- var edgeVal2 = Math.min(pi.z[0][0], pi.z[0][1]);
- prefixBoundary = (!pi.edgepaths.length && edgeVal2 > pi.level);
- }
-
- if(prefixBoundary) {
- // TODO: why does ^^ not work for constraints?
- // pi.prefixBoundary gets set by closeBoundaries
- return 'M' + perimeter.join('L') + 'Z';
- }
- return '';
-}
-
-function joinAllPaths(pi, perimeter) {
- var fullpath = initFullPath(pi, perimeter);
- var i = 0;
- var startsleft = pi.edgepaths.map(function(v, i) { return i; });
- var newloop = true;
- var endpt;
- var newendpt;
- var cnt;
- var nexti;
- var possiblei;
- var addpath;
-
- function istop(pt) { return Math.abs(pt[1] - perimeter[0][1]) < 0.01; }
- function isbottom(pt) { return Math.abs(pt[1] - perimeter[2][1]) < 0.01; }
- function isleft(pt) { return Math.abs(pt[0] - perimeter[0][0]) < 0.01; }
- function isright(pt) { return Math.abs(pt[0] - perimeter[2][0]) < 0.01; }
-
- while(startsleft.length) {
- addpath = Drawing.smoothopen(pi.edgepaths[i], pi.smoothing);
- fullpath += newloop ? addpath : addpath.replace(/^M/, 'L');
- startsleft.splice(startsleft.indexOf(i), 1);
- endpt = pi.edgepaths[i][pi.edgepaths[i].length - 1];
- nexti = -1;
-
- // now loop through sides, moving our endpoint until we find a new start
- for(cnt = 0; cnt < 4; cnt++) { // just to prevent infinite loops
- if(!endpt) {
- Lib.log('Missing end?', i, pi);
- break;
- }
-
- if(istop(endpt) && !isright(endpt)) newendpt = perimeter[1]; // right top
- else if(isleft(endpt)) newendpt = perimeter[0]; // left top
- else if(isbottom(endpt)) newendpt = perimeter[3]; // right bottom
- else if(isright(endpt)) newendpt = perimeter[2]; // left bottom
-
- for(possiblei = 0; possiblei < pi.edgepaths.length; possiblei++) {
- var ptNew = pi.edgepaths[possiblei][0];
- // is ptNew on the (horz. or vert.) segment from endpt to newendpt?
- if(Math.abs(endpt[0] - newendpt[0]) < 0.01) {
- if(Math.abs(endpt[0] - ptNew[0]) < 0.01 &&
- (ptNew[1] - endpt[1]) * (newendpt[1] - ptNew[1]) >= 0) {
- newendpt = ptNew;
- nexti = possiblei;
- }
- } else if(Math.abs(endpt[1] - newendpt[1]) < 0.01) {
- if(Math.abs(endpt[1] - ptNew[1]) < 0.01 &&
- (ptNew[0] - endpt[0]) * (newendpt[0] - ptNew[0]) >= 0) {
- newendpt = ptNew;
- nexti = possiblei;
- }
- } else {
- Lib.log('endpt to newendpt is not vert. or horz.',
- endpt, newendpt, ptNew);
- }
- }
-
- endpt = newendpt;
-
- if(nexti >= 0) break;
- fullpath += 'L' + newendpt;
- }
-
- if(nexti === pi.edgepaths.length) {
- Lib.log('unclosed perimeter path');
- break;
- }
-
- i = nexti;
-
- // if we closed back on a loop we already included,
- // close it and start a new loop
- newloop = (startsleft.indexOf(i) === -1);
- if(newloop) {
- i = startsleft[0];
- fullpath += 'Z';
- }
- }
-
- // finally add the interior paths
- for(i = 0; i < pi.paths.length; i++) {
- fullpath += Drawing.smoothclosed(pi.paths[i], pi.smoothing);
- }
-
- return fullpath;
-}
-
-function makeLinesAndLabels(plotgroup, pathinfo, gd, cd0, contours) {
- var lineContainer = Lib.ensureSingle(plotgroup, 'g', 'contourlines');
- var showLines = contours.showlines !== false;
- var showLabels = contours.showlabels;
- var clipLinesForLabels = showLines && showLabels;
-
- // Even if we're not going to show lines, we need to create them
- // if we're showing labels, because the fill paths include the perimeter
- // so can't be used to position the labels correctly.
- // In this case we'll remove the lines after making the labels.
- var linegroup = exports.createLines(lineContainer, showLines || showLabels, pathinfo);
-
- var lineClip = exports.createLineClip(lineContainer, clipLinesForLabels, gd, cd0.trace.uid);
-
- var labelGroup = plotgroup.selectAll('g.contourlabels')
- .data(showLabels ? [0] : []);
-
- labelGroup.exit().remove();
-
- labelGroup.enter().append('g')
- .classed('contourlabels', true);
-
- if(showLabels) {
- var labelClipPathData = [];
- var labelData = [];
-
- // invalidate the getTextLocation cache in case paths changed
- Lib.clearLocationCache();
-
- var contourFormat = exports.labelFormatter(contours, cd0.t.cb, gd._fullLayout);
-
- var dummyText = Drawing.tester.append('text')
- .attr('data-notex', 1)
- .call(Drawing.font, contours.labelfont);
-
- var xa = pathinfo[0].xaxis;
- var ya = pathinfo[0].yaxis;
- var xLen = xa._length;
- var yLen = ya._length;
- var xRng = xa.range;
- var yRng = ya.range;
- var xMin = Lib.aggNums(Math.min, null, cd0.x);
- var xMax = Lib.aggNums(Math.max, null, cd0.x);
- var yMin = Lib.aggNums(Math.min, null, cd0.y);
- var yMax = Lib.aggNums(Math.max, null, cd0.y);
- var x0 = Math.max(xa.c2p(xMin, true), 0);
- var x1 = Math.min(xa.c2p(xMax, true), xLen);
- var y0 = Math.max(ya.c2p(yMax, true), 0);
- var y1 = Math.min(ya.c2p(yMin, true), yLen);
-
- // visible bounds of the contour trace (and the midpoints, to
- // help with cost calculations)
- var bounds = {};
-
- if(xRng[0] < xRng[1]) {
- bounds.left = x0;
- bounds.right = x1;
- } else {
- bounds.left = x1;
- bounds.right = x0;
- }
-
- if(yRng[0] < yRng[1]) {
- bounds.top = y0;
- bounds.bottom = y1;
- } else {
- bounds.top = y1;
- bounds.bottom = y0;
- }
-
- bounds.middle = (bounds.top + bounds.bottom) / 2;
- bounds.center = (bounds.left + bounds.right) / 2;
-
- labelClipPathData.push([
- [bounds.left, bounds.top],
- [bounds.right, bounds.top],
- [bounds.right, bounds.bottom],
- [bounds.left, bounds.bottom]
- ]);
-
- var plotDiagonal = Math.sqrt(xLen * xLen + yLen * yLen);
-
- // the path length to use to scale the number of labels to draw:
- var normLength = constants.LABELDISTANCE * plotDiagonal /
- Math.max(1, pathinfo.length / constants.LABELINCREASE);
-
- linegroup.each(function(d) {
- var textOpts = exports.calcTextOpts(d.level, contourFormat, dummyText, gd);
-
- d3.select(this).selectAll('path').each(function() {
- var path = this;
- var pathBounds = Lib.getVisibleSegment(path, bounds, textOpts.height / 2);
- if(!pathBounds) return;
-
- if(pathBounds.len < (textOpts.width + textOpts.height) * constants.LABELMIN) return;
-
- var maxLabels = Math.min(Math.ceil(pathBounds.len / normLength),
- constants.LABELMAX);
-
- for(var i = 0; i < maxLabels; i++) {
- var loc = exports.findBestTextLocation(path, pathBounds, textOpts,
- labelData, bounds);
-
- if(!loc) break;
-
- exports.addLabelData(loc, textOpts, labelData, labelClipPathData);
- }
- });
- });
-
- dummyText.remove();
-
- exports.drawLabels(labelGroup, labelData, gd, lineClip,
- clipLinesForLabels ? labelClipPathData : null);
- }
-
- if(showLabels && !showLines) linegroup.remove();
-}
-
-exports.createLines = function(lineContainer, makeLines, pathinfo) {
- var smoothing = pathinfo[0].smoothing;
-
- var linegroup = lineContainer.selectAll('g.contourlevel')
- .data(makeLines ? pathinfo : []);
-
- linegroup.exit().remove();
- linegroup.enter().append('g')
- .classed('contourlevel', true);
-
- if(makeLines) {
- // pedgepaths / ppaths are used by contourcarpet, for the paths transformed from a/b to x/y
- // edgepaths / paths are used by contour since it's in x/y from the start
- var opencontourlines = linegroup.selectAll('path.openline')
- .data(function(d) { return d.pedgepaths || d.edgepaths; });
-
- opencontourlines.exit().remove();
- opencontourlines.enter().append('path')
- .classed('openline', true);
-
- opencontourlines
- .attr('d', function(d) {
- return Drawing.smoothopen(d, smoothing);
- })
- .style('stroke-miterlimit', 1)
- .style('vector-effect', 'non-scaling-stroke');
-
- var closedcontourlines = linegroup.selectAll('path.closedline')
- .data(function(d) { return d.ppaths || d.paths; });
-
- closedcontourlines.exit().remove();
- closedcontourlines.enter().append('path')
- .classed('closedline', true);
-
- closedcontourlines
- .attr('d', function(d) {
- return Drawing.smoothclosed(d, smoothing);
- })
- .style('stroke-miterlimit', 1)
- .style('vector-effect', 'non-scaling-stroke');
- }
-
- return linegroup;
-};
-
-exports.createLineClip = function(lineContainer, clipLinesForLabels, gd, uid) {
- var clips = gd._fullLayout._clips;
- var clipId = clipLinesForLabels ? ('clipline' + uid) : null;
-
- var lineClip = clips.selectAll('#' + clipId)
- .data(clipLinesForLabels ? [0] : []);
- lineClip.exit().remove();
-
- lineClip.enter().append('clipPath')
- .classed('contourlineclip', true)
- .attr('id', clipId);
-
- Drawing.setClipUrl(lineContainer, clipId, gd);
-
- return lineClip;
-};
-
-exports.labelFormatter = function(contours, colorbar, fullLayout) {
- if(contours.labelformat) {
- return fullLayout._d3locale.numberFormat(contours.labelformat);
- } else {
- var formatAxis;
- if(colorbar) {
- formatAxis = colorbar.axis;
- } else {
- formatAxis = {
- type: 'linear',
- _id: 'ycontour',
- showexponent: 'all',
- exponentformat: 'B'
- };
-
- if(contours.type === 'constraint') {
- var value = contours.value;
- if(Array.isArray(value)) {
- formatAxis.range = [value[0], value[value.length - 1]];
- } else formatAxis.range = [value, value];
- } else {
- formatAxis.range = [contours.start, contours.end];
- formatAxis.nticks = (contours.end - contours.start) / contours.size;
- }
-
- if(formatAxis.range[0] === formatAxis.range[1]) {
- formatAxis.range[1] += formatAxis.range[0] || 1;
- }
- if(!formatAxis.nticks) formatAxis.nticks = 1000;
-
- setConvert(formatAxis, fullLayout);
- Axes.prepTicks(formatAxis);
- formatAxis._tmin = null;
- formatAxis._tmax = null;
- }
- return function(v) {
- return Axes.tickText(formatAxis, v).text;
- };
- }
-};
-
-exports.calcTextOpts = function(level, contourFormat, dummyText, gd) {
- var text = contourFormat(level);
- dummyText.text(text)
- .call(svgTextUtils.convertToTspans, gd);
- var bBox = Drawing.bBox(dummyText.node(), true);
-
- return {
- text: text,
- width: bBox.width,
- height: bBox.height,
- level: level,
- dy: (bBox.top + bBox.bottom) / 2
- };
-};
-
-exports.findBestTextLocation = function(path, pathBounds, textOpts, labelData, plotBounds) {
- var textWidth = textOpts.width;
-
- var p0, dp, pMax, pMin, loc;
- if(pathBounds.isClosed) {
- dp = pathBounds.len / costConstants.INITIALSEARCHPOINTS;
- p0 = pathBounds.min + dp / 2;
- pMax = pathBounds.max;
- } else {
- dp = (pathBounds.len - textWidth) / (costConstants.INITIALSEARCHPOINTS + 1);
- p0 = pathBounds.min + dp + textWidth / 2;
- pMax = pathBounds.max - (dp + textWidth) / 2;
- }
-
- var cost = Infinity;
- for(var j = 0; j < costConstants.ITERATIONS; j++) {
- for(var p = p0; p < pMax; p += dp) {
- var newLocation = Lib.getTextLocation(path, pathBounds.total, p, textWidth);
- var newCost = locationCost(newLocation, textOpts, labelData, plotBounds);
- if(newCost < cost) {
- cost = newCost;
- loc = newLocation;
- pMin = p;
- }
- }
- if(cost > costConstants.MAXCOST * 2) break;
-
- // subsequent iterations just look half steps away from the
- // best we found in the previous iteration
- if(j) dp /= 2;
- p0 = pMin - dp / 2;
- pMax = p0 + dp * 1.5;
- }
- if(cost <= costConstants.MAXCOST) return loc;
-};
-
-/*
- * locationCost: a cost function for label locations
- * composed of three kinds of penalty:
- * - for open paths, being close to the end of the path
- * - the angle away from horizontal
- * - being too close to already placed neighbors
- */
-function locationCost(loc, textOpts, labelData, bounds) {
- var halfWidth = textOpts.width / 2;
- var halfHeight = textOpts.height / 2;
- var x = loc.x;
- var y = loc.y;
- var theta = loc.theta;
- var dx = Math.cos(theta) * halfWidth;
- var dy = Math.sin(theta) * halfWidth;
-
- // cost for being near an edge
- var normX = ((x > bounds.center) ? (bounds.right - x) : (x - bounds.left)) /
- (dx + Math.abs(Math.sin(theta) * halfHeight));
- var normY = ((y > bounds.middle) ? (bounds.bottom - y) : (y - bounds.top)) /
- (Math.abs(dy) + Math.cos(theta) * halfHeight);
- if(normX < 1 || normY < 1) return Infinity;
- var cost = costConstants.EDGECOST * (1 / (normX - 1) + 1 / (normY - 1));
-
- // cost for not being horizontal
- cost += costConstants.ANGLECOST * theta * theta;
-
- // cost for being close to other labels
- var x1 = x - dx;
- var y1 = y - dy;
- var x2 = x + dx;
- var y2 = y + dy;
- for(var i = 0; i < labelData.length; i++) {
- var labeli = labelData[i];
- var dxd = Math.cos(labeli.theta) * labeli.width / 2;
- var dyd = Math.sin(labeli.theta) * labeli.width / 2;
- var dist = Lib.segmentDistance(
- x1, y1,
- x2, y2,
- labeli.x - dxd, labeli.y - dyd,
- labeli.x + dxd, labeli.y + dyd
- ) * 2 / (textOpts.height + labeli.height);
-
- var sameLevel = labeli.level === textOpts.level;
- var distOffset = sameLevel ? costConstants.SAMELEVELDISTANCE : 1;
-
- if(dist <= distOffset) return Infinity;
-
- var distFactor = costConstants.NEIGHBORCOST *
- (sameLevel ? costConstants.SAMELEVELFACTOR : 1);
-
- cost += distFactor / (dist - distOffset);
- }
-
- return cost;
-}
-
-exports.addLabelData = function(loc, textOpts, labelData, labelClipPathData) {
- var halfWidth = textOpts.width / 2;
- var halfHeight = textOpts.height / 2;
-
- var x = loc.x;
- var y = loc.y;
- var theta = loc.theta;
-
- var sin = Math.sin(theta);
- var cos = Math.cos(theta);
- var dxw = halfWidth * cos;
- var dxh = halfHeight * sin;
- var dyw = halfWidth * sin;
- var dyh = -halfHeight * cos;
- var bBoxPts = [
- [x - dxw - dxh, y - dyw - dyh],
- [x + dxw - dxh, y + dyw - dyh],
- [x + dxw + dxh, y + dyw + dyh],
- [x - dxw + dxh, y - dyw + dyh],
- ];
-
- labelData.push({
- text: textOpts.text,
- x: x,
- y: y,
- dy: textOpts.dy,
- theta: theta,
- level: textOpts.level,
- width: textOpts.width,
- height: textOpts.height
- });
-
- labelClipPathData.push(bBoxPts);
-};
-
-exports.drawLabels = function(labelGroup, labelData, gd, lineClip, labelClipPathData) {
- var labels = labelGroup.selectAll('text')
- .data(labelData, function(d) {
- return d.text + ',' + d.x + ',' + d.y + ',' + d.theta;
- });
-
- labels.exit().remove();
-
- labels.enter().append('text')
- .attr({
- 'data-notex': 1,
- 'text-anchor': 'middle'
- })
- .each(function(d) {
- var x = d.x + Math.sin(d.theta) * d.dy;
- var y = d.y - Math.cos(d.theta) * d.dy;
- d3.select(this)
- .text(d.text)
- .attr({
- x: x,
- y: y,
- transform: 'rotate(' + (180 * d.theta / Math.PI) + ' ' + x + ' ' + y + ')'
- })
- .call(svgTextUtils.convertToTspans, gd);
- });
-
- if(labelClipPathData) {
- var clipPath = '';
- for(var i = 0; i < labelClipPathData.length; i++) {
- clipPath += 'M' + labelClipPathData[i].join('L') + 'Z';
- }
-
- var lineClipPath = Lib.ensureSingle(lineClip, 'path', '');
- lineClipPath.attr('d', clipPath);
- }
-};
-
-function clipGaps(plotGroup, plotinfo, gd, cd0, perimeter) {
- var clips = gd._fullLayout._clips;
- var clipId = 'clip' + cd0.trace.uid;
-
- var clipPath = clips.selectAll('#' + clipId)
- .data(cd0.trace.connectgaps ? [] : [0]);
- clipPath.enter().append('clipPath')
- .classed('contourclip', true)
- .attr('id', clipId);
- clipPath.exit().remove();
-
- if(cd0.trace.connectgaps === false) {
- var clipPathInfo = {
- // fraction of the way from missing to present point
- // to draw the boundary.
- // if you make this 1 (or 1-epsilon) then a point in
- // a sea of missing data will disappear entirely.
- level: 0.9,
- crossings: {},
- starts: [],
- edgepaths: [],
- paths: [],
- xaxis: plotinfo.xaxis,
- yaxis: plotinfo.yaxis,
- x: cd0.x,
- y: cd0.y,
- // 0 = no data, 1 = data
- z: makeClipMask(cd0),
- smoothing: 0
- };
-
- makeCrossings([clipPathInfo]);
- findAllPaths([clipPathInfo]);
- var fullpath = joinAllPaths(clipPathInfo, perimeter);
-
- var path = Lib.ensureSingle(clipPath, 'path', '');
- path.attr('d', fullpath);
- } else clipId = null;
-
- Drawing.setClipUrl(plotGroup, clipId, gd);
-}
-
-function makeClipMask(cd0) {
- var empties = cd0.trace._emptypoints;
- var z = [];
- var m = cd0.z.length;
- var n = cd0.z[0].length;
- var i;
- var row = [];
- var emptyPoint;
-
- for(i = 0; i < n; i++) row.push(1);
- for(i = 0; i < m; i++) z.push(row.slice());
- for(i = 0; i < empties.length; i++) {
- emptyPoint = empties[i];
- z[emptyPoint[0]][emptyPoint[1]] = 0;
- }
- // save this mask to determine whether to show this data in hover
- cd0.zmask = z;
- return z;
-}
-
-},{"../../components/drawing":72,"../../lib":168,"../../lib/svg_text_utils":189,"../../plots/cartesian/axes":212,"../../plots/cartesian/set_convert":230,"../heatmap/plot":326,"./close_boundaries":295,"./constants":297,"./convert_to_constraints":301,"./empty_pathinfo":303,"./find_all_paths":305,"./make_crossings":310,"d3":16}],312:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Axes = _dereq_('../../plots/cartesian/axes');
-var Lib = _dereq_('../../lib');
-
-module.exports = function setContours(trace, vals) {
- var contours = trace.contours;
-
- // check if we need to auto-choose contour levels
- if(trace.autocontour) {
- // N.B. do not try to use coloraxis cmin/cmax,
- // these values here are meant to remain "per-trace" for now
- var zmin = trace.zmin;
- var zmax = trace.zmax;
- if(trace.zauto || zmin === undefined) {
- zmin = Lib.aggNums(Math.min, null, vals);
- }
- if(trace.zauto || zmax === undefined) {
- zmax = Lib.aggNums(Math.max, null, vals);
- }
-
- var dummyAx = autoContours(zmin, zmax, trace.ncontours);
- contours.size = dummyAx.dtick;
- contours.start = Axes.tickFirst(dummyAx);
- dummyAx.range.reverse();
- contours.end = Axes.tickFirst(dummyAx);
-
- if(contours.start === zmin) contours.start += contours.size;
- if(contours.end === zmax) contours.end -= contours.size;
-
- // if you set a small ncontours, *and* the ends are exactly on zmin/zmax
- // there's an edge case where start > end now. Make sure there's at least
- // one meaningful contour, put it midway between the crossed values
- if(contours.start > contours.end) {
- contours.start = contours.end = (contours.start + contours.end) / 2;
- }
-
- // copy auto-contour info back to the source data.
- // previously we copied the whole contours object back, but that had
- // other info (coloring, showlines) that should be left to supplyDefaults
- if(!trace._input.contours) trace._input.contours = {};
- Lib.extendFlat(trace._input.contours, {
- start: contours.start,
- end: contours.end,
- size: contours.size
- });
- trace._input.autocontour = true;
- } else if(contours.type !== 'constraint') {
- // sanity checks on manually-supplied start/end/size
- var start = contours.start;
- var end = contours.end;
- var inputContours = trace._input.contours;
-
- if(start > end) {
- contours.start = inputContours.start = end;
- end = contours.end = inputContours.end = start;
- start = contours.start;
- }
-
- if(!(contours.size > 0)) {
- var sizeOut;
- if(start === end) sizeOut = 1;
- else sizeOut = autoContours(start, end, trace.ncontours).dtick;
-
- inputContours.size = contours.size = sizeOut;
- }
- }
-};
-
-
-/*
- * autoContours: make a dummy axis object with dtick we can use
- * as contours.size, and if needed we can use Axes.tickFirst
- * with this axis object to calculate the start and end too
- *
- * start: the value to start the contours at
- * end: the value to end at (must be > start)
- * ncontours: max number of contours to make, like roughDTick
- *
- * returns: an axis object
- */
-function autoContours(start, end, ncontours) {
- var dummyAx = {
- type: 'linear',
- range: [start, end]
- };
-
- Axes.autoTicks(
- dummyAx,
- (end - start) / (ncontours || 15)
- );
-
- return dummyAx;
-}
-
-},{"../../lib":168,"../../plots/cartesian/axes":212}],313:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var d3 = _dereq_('d3');
-
-var Drawing = _dereq_('../../components/drawing');
-var heatmapStyle = _dereq_('../heatmap/style');
-
-var makeColorMap = _dereq_('./make_color_map');
-
-
-module.exports = function style(gd) {
- var contours = d3.select(gd).selectAll('g.contour');
-
- contours.style('opacity', function(d) {
- return d[0].trace.opacity;
- });
-
- contours.each(function(d) {
- var c = d3.select(this);
- var trace = d[0].trace;
- var contours = trace.contours;
- var line = trace.line;
- var cs = contours.size || 1;
- var start = contours.start;
-
- // for contourcarpet only - is this a constraint-type contour trace?
- var isConstraintType = contours.type === 'constraint';
- var colorLines = !isConstraintType && contours.coloring === 'lines';
- var colorFills = !isConstraintType && contours.coloring === 'fill';
-
- var colorMap = (colorLines || colorFills) ? makeColorMap(trace) : null;
-
- c.selectAll('g.contourlevel').each(function(d) {
- d3.select(this).selectAll('path')
- .call(Drawing.lineGroupStyle,
- line.width,
- colorLines ? colorMap(d.level) : line.color,
- line.dash);
- });
-
- var labelFont = contours.labelfont;
- c.selectAll('g.contourlabels text').each(function(d) {
- Drawing.font(d3.select(this), {
- family: labelFont.family,
- size: labelFont.size,
- color: labelFont.color || (colorLines ? colorMap(d.level) : line.color)
- });
- });
-
- if(isConstraintType) {
- c.selectAll('g.contourfill path')
- .style('fill', trace.fillcolor);
- } else if(colorFills) {
- var firstFill;
-
- c.selectAll('g.contourfill path')
- .style('fill', function(d) {
- if(firstFill === undefined) firstFill = d.level;
- return colorMap(d.level + 0.5 * cs);
- });
-
- if(firstFill === undefined) firstFill = start;
-
- c.selectAll('g.contourbg path')
- .style('fill', colorMap(firstFill - 0.5 * cs));
- }
- });
-
- heatmapStyle(gd);
-};
-
-},{"../../components/drawing":72,"../heatmap/style":327,"./make_color_map":309,"d3":16}],314:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var colorscaleDefaults = _dereq_('../../components/colorscale/defaults');
-var handleLabelDefaults = _dereq_('./label_defaults');
-
-
-module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, layout, opts) {
- var coloring = coerce('contours.coloring');
-
- var showLines;
- var lineColor = '';
- if(coloring === 'fill') showLines = coerce('contours.showlines');
-
- if(showLines !== false) {
- if(coloring !== 'lines') lineColor = coerce('line.color', '#000');
- coerce('line.width', 0.5);
- coerce('line.dash');
- }
-
- if(coloring !== 'none') {
- // plots/plots always coerces showlegend to true, but in this case
- // we default to false and (by default) show a colorbar instead
- if(traceIn.showlegend !== true) traceOut.showlegend = false;
- traceOut._dfltShowLegend = false;
-
- colorscaleDefaults(
- traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'}
- );
- }
-
- coerce('line.smoothing');
-
- handleLabelDefaults(coerce, layout, lineColor, opts);
-};
-
-},{"../../components/colorscale/defaults":61,"./label_defaults":308}],315:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var scatterAttrs = _dereq_('../scatter/attributes');
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
-var colorScaleAttrs = _dereq_('../../components/colorscale/attributes');
-
-var extendFlat = _dereq_('../../lib/extend').extendFlat;
-
-module.exports = extendFlat({
- z: {
- valType: 'data_array',
- editType: 'calc',
-
- },
- x: extendFlat({}, scatterAttrs.x, {impliedEdits: {xtype: 'array'}}),
- x0: extendFlat({}, scatterAttrs.x0, {impliedEdits: {xtype: 'scaled'}}),
- dx: extendFlat({}, scatterAttrs.dx, {impliedEdits: {xtype: 'scaled'}}),
- y: extendFlat({}, scatterAttrs.y, {impliedEdits: {ytype: 'array'}}),
- y0: extendFlat({}, scatterAttrs.y0, {impliedEdits: {ytype: 'scaled'}}),
- dy: extendFlat({}, scatterAttrs.dy, {impliedEdits: {ytype: 'scaled'}}),
-
- text: {
- valType: 'data_array',
- editType: 'calc',
-
- },
- hovertext: {
- valType: 'data_array',
- editType: 'calc',
-
- },
- transpose: {
- valType: 'boolean',
- dflt: false,
-
- editType: 'calc',
-
- },
- xtype: {
- valType: 'enumerated',
- values: ['array', 'scaled'],
-
- editType: 'calc+clearAxisTypes',
-
- },
- ytype: {
- valType: 'enumerated',
- values: ['array', 'scaled'],
-
- editType: 'calc+clearAxisTypes',
-
- },
- zsmooth: {
- valType: 'enumerated',
- values: ['fast', 'best', false],
- dflt: false,
-
- editType: 'calc',
-
- },
- connectgaps: {
- valType: 'boolean',
- dflt: false,
-
- editType: 'calc',
-
- },
- xgap: {
- valType: 'number',
- dflt: 0,
- min: 0,
-
- editType: 'plot',
-
- },
- ygap: {
- valType: 'number',
- dflt: 0,
- min: 0,
-
- editType: 'plot',
-
- },
- zhoverformat: {
- valType: 'string',
- dflt: '',
-
- editType: 'none',
-
- },
- hovertemplate: hovertemplateAttrs()
-}, {
- transforms: undefined
-},
- colorScaleAttrs('', {cLetter: 'z', autoColorDflt: false})
-);
-
-},{"../../components/colorscale/attributes":58,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../scatter/attributes":365}],316:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Registry = _dereq_('../../registry');
-var Lib = _dereq_('../../lib');
-var Axes = _dereq_('../../plots/cartesian/axes');
-
-var histogram2dCalc = _dereq_('../histogram2d/calc');
-var colorscaleCalc = _dereq_('../../components/colorscale/calc');
-var convertColumnData = _dereq_('./convert_column_xyz');
-var clean2dArray = _dereq_('./clean_2d_array');
-var interp2d = _dereq_('./interp2d');
-var findEmpties = _dereq_('./find_empties');
-var makeBoundArray = _dereq_('./make_bound_array');
-
-module.exports = function calc(gd, trace) {
- // prepare the raw data
- // run makeCalcdata on x and y even for heatmaps, in case of category mappings
- var xa = Axes.getFromId(gd, trace.xaxis || 'x');
- var ya = Axes.getFromId(gd, trace.yaxis || 'y');
- var isContour = Registry.traceIs(trace, 'contour');
- var isHist = Registry.traceIs(trace, 'histogram');
- var isGL2D = Registry.traceIs(trace, 'gl2d');
- var zsmooth = isContour ? 'best' : trace.zsmooth;
- var x;
- var x0;
- var dx;
- var y;
- var y0;
- var dy;
- var z;
- var i;
- var binned;
-
- // cancel minimum tick spacings (only applies to bars and boxes)
- xa._minDtick = 0;
- ya._minDtick = 0;
-
- if(isHist) {
- binned = histogram2dCalc(gd, trace);
- x = binned.x;
- x0 = binned.x0;
- dx = binned.dx;
- y = binned.y;
- y0 = binned.y0;
- dy = binned.dy;
- z = binned.z;
- } else {
- var zIn = trace.z;
- if(Lib.isArray1D(zIn)) {
- convertColumnData(trace, xa, ya, 'x', 'y', ['z']);
- x = trace._x;
- y = trace._y;
- zIn = trace._z;
- } else {
- x = trace._x = trace.x ? xa.makeCalcdata(trace, 'x') : [];
- y = trace._y = trace.y ? ya.makeCalcdata(trace, 'y') : [];
- }
-
- x0 = trace.x0;
- dx = trace.dx;
- y0 = trace.y0;
- dy = trace.dy;
-
- z = clean2dArray(zIn, trace, xa, ya);
-
- if(isContour || trace.connectgaps) {
- trace._emptypoints = findEmpties(z);
- interp2d(z, trace._emptypoints);
- }
- }
-
- function noZsmooth(msg) {
- zsmooth = trace._input.zsmooth = trace.zsmooth = false;
- Lib.warn('cannot use zsmooth: "fast": ' + msg);
- }
-
- // check whether we really can smooth (ie all boxes are about the same size)
- if(zsmooth === 'fast') {
- if(xa.type === 'log' || ya.type === 'log') {
- noZsmooth('log axis found');
- } else if(!isHist) {
- if(x.length) {
- var avgdx = (x[x.length - 1] - x[0]) / (x.length - 1);
- var maxErrX = Math.abs(avgdx / 100);
- for(i = 0; i < x.length - 1; i++) {
- if(Math.abs(x[i + 1] - x[i] - avgdx) > maxErrX) {
- noZsmooth('x scale is not linear');
- break;
- }
- }
- }
- if(y.length && zsmooth === 'fast') {
- var avgdy = (y[y.length - 1] - y[0]) / (y.length - 1);
- var maxErrY = Math.abs(avgdy / 100);
- for(i = 0; i < y.length - 1; i++) {
- if(Math.abs(y[i + 1] - y[i] - avgdy) > maxErrY) {
- noZsmooth('y scale is not linear');
- break;
- }
- }
- }
- }
- }
-
- // create arrays of brick boundaries, to be used by autorange and heatmap.plot
- var xlen = Lib.maxRowLength(z);
- var xIn = trace.xtype === 'scaled' ? '' : x;
- var xArray = makeBoundArray(trace, xIn, x0, dx, xlen, xa);
- var yIn = trace.ytype === 'scaled' ? '' : y;
- var yArray = makeBoundArray(trace, yIn, y0, dy, z.length, ya);
-
- // handled in gl2d convert step
- if(!isGL2D) {
- trace._extremes[xa._id] = Axes.findExtremes(xa, xArray);
- trace._extremes[ya._id] = Axes.findExtremes(ya, yArray);
- }
-
- var cd0 = {
- x: xArray,
- y: yArray,
- z: z,
- text: trace._text || trace.text,
- hovertext: trace._hovertext || trace.hovertext
- };
-
- if(xIn && xIn.length === xArray.length - 1) cd0.xCenter = xIn;
- if(yIn && yIn.length === yArray.length - 1) cd0.yCenter = yIn;
-
- if(isHist) {
- cd0.xRanges = binned.xRanges;
- cd0.yRanges = binned.yRanges;
- cd0.pts = binned.pts;
- }
-
- if(!isContour) {
- colorscaleCalc(gd, trace, {vals: z, cLetter: 'z'});
- }
-
- if(isContour && trace.contours && trace.contours.coloring === 'heatmap') {
- var dummyTrace = {
- type: trace.type === 'contour' ? 'heatmap' : 'histogram2d',
- xcalendar: trace.xcalendar,
- ycalendar: trace.ycalendar
- };
- cd0.xfill = makeBoundArray(dummyTrace, xIn, x0, dx, xlen, xa);
- cd0.yfill = makeBoundArray(dummyTrace, yIn, y0, dy, z.length, ya);
- }
-
- return [cd0];
-};
-
-},{"../../components/colorscale/calc":59,"../../lib":168,"../../plots/cartesian/axes":212,"../../registry":256,"../histogram2d/calc":344,"./clean_2d_array":317,"./convert_column_xyz":319,"./find_empties":321,"./interp2d":324,"./make_bound_array":325}],317:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var isNumeric = _dereq_('fast-isnumeric');
-var Lib = _dereq_('../../lib');
-var BADNUM = _dereq_('../../constants/numerical').BADNUM;
-
-module.exports = function clean2dArray(zOld, trace, xa, ya) {
- var rowlen, collen, getCollen, old2new, i, j;
-
- function cleanZvalue(v) {
- if(!isNumeric(v)) return undefined;
- return +v;
- }
-
- if(trace && trace.transpose) {
- rowlen = 0;
- for(i = 0; i < zOld.length; i++) rowlen = Math.max(rowlen, zOld[i].length);
- if(rowlen === 0) return false;
- getCollen = function(zOld) { return zOld.length; };
- old2new = function(zOld, i, j) { return zOld[j][i]; };
- } else {
- rowlen = zOld.length;
- getCollen = function(zOld, i) { return zOld[i].length; };
- old2new = function(zOld, i, j) { return zOld[i][j]; };
- }
-
- var padOld2new = function(zOld, i, j) {
- if(i === BADNUM || j === BADNUM) return BADNUM;
- return old2new(zOld, i, j);
- };
-
- function axisMapping(ax) {
- if(trace && trace.type !== 'carpet' && trace.type !== 'contourcarpet' &&
- ax && ax.type === 'category' && trace['_' + ax._id.charAt(0)].length) {
- var axLetter = ax._id.charAt(0);
- var axMapping = {};
- var traceCategories = trace['_' + axLetter + 'CategoryMap'] || trace[axLetter];
- for(i = 0; i < traceCategories.length; i++) {
- axMapping[traceCategories[i]] = i;
- }
- return function(i) {
- var ind = axMapping[ax._categories[i]];
- return ind + 1 ? ind : BADNUM;
- };
- } else {
- return Lib.identity;
- }
- }
-
- var xMap = axisMapping(xa);
- var yMap = axisMapping(ya);
-
- var zNew = new Array(rowlen);
-
- if(ya && ya.type === 'category') rowlen = ya._categories.length;
- for(i = 0; i < rowlen; i++) {
- if(xa && xa.type === 'category') {
- collen = xa._categories.length;
- } else {
- collen = getCollen(zOld, i);
- }
- zNew[i] = new Array(collen);
- for(j = 0; j < collen; j++) zNew[i][j] = cleanZvalue(padOld2new(zOld, yMap(i), xMap(j)));
- }
-
- return zNew;
-};
-
-},{"../../constants/numerical":149,"../../lib":168,"fast-isnumeric":18}],318:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = {
- min: 'zmin',
- max: 'zmax'
-};
-
-},{}],319:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var BADNUM = _dereq_('../../constants/numerical').BADNUM;
-
-module.exports = function convertColumnData(trace, ax1, ax2, var1Name, var2Name, arrayVarNames) {
- var colLen = trace._length;
- var col1 = ax1.makeCalcdata(trace, var1Name);
- var col2 = ax2.makeCalcdata(trace, var2Name);
- var textCol = trace.text;
- var hasColumnText = (textCol !== undefined && Lib.isArray1D(textCol));
- var hoverTextCol = trace.hovertext;
- var hasColumnHoverText = (hoverTextCol !== undefined && Lib.isArray1D(hoverTextCol));
- var i, j;
-
- var col1dv = Lib.distinctVals(col1);
- var col1vals = col1dv.vals;
- var col2dv = Lib.distinctVals(col2);
- var col2vals = col2dv.vals;
- var newArrays = [];
- var text;
- var hovertext;
-
- for(i = 0; i < arrayVarNames.length; i++) {
- newArrays[i] = Lib.init2dArray(col2vals.length, col1vals.length);
- }
-
- if(hasColumnText) {
- text = Lib.init2dArray(col2vals.length, col1vals.length);
- }
- if(hasColumnHoverText) {
- hovertext = Lib.init2dArray(col2vals.length, col1vals.length);
- }
-
- for(i = 0; i < colLen; i++) {
- if(col1[i] !== BADNUM && col2[i] !== BADNUM) {
- var i1 = Lib.findBin(col1[i] + col1dv.minDiff / 2, col1vals);
- var i2 = Lib.findBin(col2[i] + col2dv.minDiff / 2, col2vals);
-
- for(j = 0; j < arrayVarNames.length; j++) {
- var arrayVarName = arrayVarNames[j];
- var arrayVar = trace[arrayVarName];
- var newArray = newArrays[j];
- newArray[i2][i1] = arrayVar[i];
- }
-
- if(hasColumnText) text[i2][i1] = textCol[i];
- if(hasColumnHoverText) hovertext[i2][i1] = hoverTextCol[i];
- }
- }
-
- trace['_' + var1Name] = col1vals;
- trace['_' + var2Name] = col2vals;
- for(j = 0; j < arrayVarNames.length; j++) {
- trace['_' + arrayVarNames[j]] = newArrays[j];
- }
- if(hasColumnText) trace._text = text;
- if(hasColumnHoverText) trace._hovertext = hovertext;
-
- if(ax1 && ax1.type === 'category') {
- trace['_' + var1Name + 'CategoryMap'] = col1vals.map(function(v) { return ax1._categories[v];});
- }
-
- if(ax2 && ax2.type === 'category') {
- trace['_' + var2Name + 'CategoryMap'] = col2vals.map(function(v) { return ax2._categories[v];});
- }
-};
-
-},{"../../constants/numerical":149,"../../lib":168}],320:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-var handleXYZDefaults = _dereq_('./xyz_defaults');
-var handleStyleDefaults = _dereq_('./style_defaults');
-var colorscaleDefaults = _dereq_('../../components/colorscale/defaults');
-var attributes = _dereq_('./attributes');
-
-
-module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
- function coerce(attr, dflt) {
- return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
- }
-
- var validData = handleXYZDefaults(traceIn, traceOut, coerce, layout);
- if(!validData) {
- traceOut.visible = false;
- return;
- }
-
- coerce('text');
- coerce('hovertext');
- coerce('hovertemplate');
-
- handleStyleDefaults(traceIn, traceOut, coerce, layout);
-
- coerce('connectgaps', Lib.isArray1D(traceOut.z) && (traceOut.zsmooth !== false));
-
- colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'});
-};
-
-},{"../../components/colorscale/defaults":61,"../../lib":168,"./attributes":315,"./style_defaults":328,"./xyz_defaults":329}],321:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var maxRowLength = _dereq_('../../lib').maxRowLength;
-
-/* Return a list of empty points in 2D array z
- * each empty point z[i][j] gives an array [i, j, neighborCount]
- * neighborCount is the count of 4 nearest neighbors that DO exist
- * this is to give us an order of points to evaluate for interpolation.
- * if no neighbors exist, we iteratively look for neighbors that HAVE
- * neighbors, and add a fractional neighborCount
- */
-module.exports = function findEmpties(z) {
- var empties = [];
- var neighborHash = {};
- var noNeighborList = [];
- var nextRow = z[0];
- var row = [];
- var blank = [0, 0, 0];
- var rowLength = maxRowLength(z);
- var prevRow;
- var i;
- var j;
- var thisPt;
- var p;
- var neighborCount;
- var newNeighborHash;
- var foundNewNeighbors;
-
- for(i = 0; i < z.length; i++) {
- prevRow = row;
- row = nextRow;
- nextRow = z[i + 1] || [];
- for(j = 0; j < rowLength; j++) {
- if(row[j] === undefined) {
- neighborCount = (row[j - 1] !== undefined ? 1 : 0) +
- (row[j + 1] !== undefined ? 1 : 0) +
- (prevRow[j] !== undefined ? 1 : 0) +
- (nextRow[j] !== undefined ? 1 : 0);
-
- if(neighborCount) {
- // for this purpose, don't count off-the-edge points
- // as undefined neighbors
- if(i === 0) neighborCount++;
- if(j === 0) neighborCount++;
- if(i === z.length - 1) neighborCount++;
- if(j === row.length - 1) neighborCount++;
-
- // if all neighbors that could exist do, we don't
- // need this for finding farther neighbors
- if(neighborCount < 4) {
- neighborHash[[i, j]] = [i, j, neighborCount];
- }
-
- empties.push([i, j, neighborCount]);
- } else noNeighborList.push([i, j]);
- }
- }
- }
-
- while(noNeighborList.length) {
- newNeighborHash = {};
- foundNewNeighbors = false;
-
- // look for cells that now have neighbors but didn't before
- for(p = noNeighborList.length - 1; p >= 0; p--) {
- thisPt = noNeighborList[p];
- i = thisPt[0];
- j = thisPt[1];
-
- neighborCount = ((neighborHash[[i - 1, j]] || blank)[2] +
- (neighborHash[[i + 1, j]] || blank)[2] +
- (neighborHash[[i, j - 1]] || blank)[2] +
- (neighborHash[[i, j + 1]] || blank)[2]) / 20;
-
- if(neighborCount) {
- newNeighborHash[thisPt] = [i, j, neighborCount];
- noNeighborList.splice(p, 1);
- foundNewNeighbors = true;
- }
- }
-
- if(!foundNewNeighbors) {
- throw 'findEmpties iterated with no new neighbors';
- }
-
- // put these new cells into the main neighbor list
- for(thisPt in newNeighborHash) {
- neighborHash[thisPt] = newNeighborHash[thisPt];
- empties.push(newNeighborHash[thisPt]);
- }
- }
-
- // sort the full list in descending order of neighbor count
- return empties.sort(function(a, b) { return b[2] - a[2]; });
-};
-
-},{"../../lib":168}],322:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Fx = _dereq_('../../components/fx');
-var Lib = _dereq_('../../lib');
-var Axes = _dereq_('../../plots/cartesian/axes');
-var extractOpts = _dereq_('../../components/colorscale').extractOpts;
-
-module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLayer, contour) {
- var cd0 = pointData.cd[0];
- var trace = cd0.trace;
- var xa = pointData.xa;
- var ya = pointData.ya;
- var x = cd0.x;
- var y = cd0.y;
- var z = cd0.z;
- var xc = cd0.xCenter;
- var yc = cd0.yCenter;
- var zmask = cd0.zmask;
- var zhoverformat = trace.zhoverformat;
- var x2 = x;
- var y2 = y;
-
- var xl, yl, nx, ny;
-
- if(pointData.index !== false) {
- try {
- nx = Math.round(pointData.index[1]);
- ny = Math.round(pointData.index[0]);
- } catch(e) {
- Lib.error('Error hovering on heatmap, ' +
- 'pointNumber must be [row,col], found:', pointData.index);
- return;
- }
- if(nx < 0 || nx >= z[0].length || ny < 0 || ny > z.length) {
- return;
- }
- } else if(Fx.inbox(xval - x[0], xval - x[x.length - 1], 0) > 0 ||
- Fx.inbox(yval - y[0], yval - y[y.length - 1], 0) > 0) {
- return;
- } else {
- if(contour) {
- var i2;
- x2 = [2 * x[0] - x[1]];
-
- for(i2 = 1; i2 < x.length; i2++) {
- x2.push((x[i2] + x[i2 - 1]) / 2);
- }
- x2.push([2 * x[x.length - 1] - x[x.length - 2]]);
-
- y2 = [2 * y[0] - y[1]];
- for(i2 = 1; i2 < y.length; i2++) {
- y2.push((y[i2] + y[i2 - 1]) / 2);
- }
- y2.push([2 * y[y.length - 1] - y[y.length - 2]]);
- }
- nx = Math.max(0, Math.min(x2.length - 2, Lib.findBin(xval, x2)));
- ny = Math.max(0, Math.min(y2.length - 2, Lib.findBin(yval, y2)));
- }
-
- var x0 = xa.c2p(x[nx]);
- var x1 = xa.c2p(x[nx + 1]);
- var y0 = ya.c2p(y[ny]);
- var y1 = ya.c2p(y[ny + 1]);
-
- if(contour) {
- x1 = x0;
- xl = x[nx];
- y1 = y0;
- yl = y[ny];
- } else {
- xl = xc ? xc[nx] : ((x[nx] + x[nx + 1]) / 2);
- yl = yc ? yc[ny] : ((y[ny] + y[ny + 1]) / 2);
-
- if(xa && xa.type === 'category') xl = x[nx];
- if(ya && ya.type === 'category') yl = y[ny];
-
- if(trace.zsmooth) {
- x0 = x1 = xa.c2p(xl);
- y0 = y1 = ya.c2p(yl);
- }
- }
-
- var zVal = z[ny][nx];
- if(zmask && !zmask[ny][nx]) zVal = undefined;
-
- var text;
- if(Array.isArray(cd0.hovertext) && Array.isArray(cd0.hovertext[ny])) {
- text = cd0.hovertext[ny][nx];
- } else if(Array.isArray(cd0.text) && Array.isArray(cd0.text[ny])) {
- text = cd0.text[ny][nx];
- }
-
- // dummy axis for formatting the z value
- var cOpts = extractOpts(trace);
- var dummyAx = {
- type: 'linear',
- range: [cOpts.min, cOpts.max],
- hoverformat: zhoverformat,
- _separators: xa._separators,
- _numFormat: xa._numFormat
- };
- var zLabel = Axes.tickText(dummyAx, zVal, 'hover').text;
-
- return [Lib.extendFlat(pointData, {
- index: [ny, nx],
- // never let a 2D override 1D type as closest point
- distance: pointData.maxHoverDistance,
- spikeDistance: pointData.maxSpikeDistance,
- x0: x0,
- x1: x1,
- y0: y0,
- y1: y1,
- xLabelVal: xl,
- yLabelVal: yl,
- zLabelVal: zVal,
- zLabel: zLabel,
- text: text
- })];
-};
-
-},{"../../components/colorscale":63,"../../components/fx":90,"../../lib":168,"../../plots/cartesian/axes":212}],323:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = {
- attributes: _dereq_('./attributes'),
- supplyDefaults: _dereq_('./defaults'),
- calc: _dereq_('./calc'),
- plot: _dereq_('./plot'),
- colorbar: _dereq_('./colorbar'),
- style: _dereq_('./style'),
- hoverPoints: _dereq_('./hover'),
-
- moduleType: 'trace',
- name: 'heatmap',
- basePlotModule: _dereq_('../../plots/cartesian'),
- categories: ['cartesian', 'svg', '2dMap'],
- meta: {
-
- }
-};
-
-},{"../../plots/cartesian":223,"./attributes":315,"./calc":316,"./colorbar":318,"./defaults":320,"./hover":322,"./plot":326,"./style":327}],324:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-var INTERPTHRESHOLD = 1e-2;
-var NEIGHBORSHIFTS = [[-1, 0], [1, 0], [0, -1], [0, 1]];
-
-function correctionOvershoot(maxFractionalChange) {
- // start with less overshoot, until we know it's converging,
- // then ramp up the overshoot for faster convergence
- return 0.5 - 0.25 * Math.min(1, maxFractionalChange * 0.5);
-}
-
-/*
- * interp2d: Fill in missing data from a 2D array using an iterative
- * poisson equation solver with zero-derivative BC at edges.
- * Amazingly, this just amounts to repeatedly averaging all the existing
- * nearest neighbors, at least if we don't take x/y scaling into account,
- * which is the right approach here where x and y may not even have the
- * same units.
- *
- * @param {array of arrays} z
- * The 2D array to fill in. Will be mutated here. Assumed to already be
- * cleaned, so all entries are numbers except gaps, which are `undefined`.
- * @param {array of arrays} emptyPoints
- * Each entry [i, j, neighborCount] for empty points z[i][j] and the number
- * of neighbors that are *not* missing. Assumed to be sorted from most to
- * least neighbors, as produced by heatmap/find_empties.
- */
-module.exports = function interp2d(z, emptyPoints) {
- var maxFractionalChange = 1;
- var i;
-
- // one pass to fill in a starting value for all the empties
- iterateInterp2d(z, emptyPoints);
-
- // we're don't need to iterate lone empties - remove them
- for(i = 0; i < emptyPoints.length; i++) {
- if(emptyPoints[i][2] < 4) break;
- }
- // but don't remove these points from the original array,
- // we'll use them for masking, so make a copy.
- emptyPoints = emptyPoints.slice(i);
-
- for(i = 0; i < 100 && maxFractionalChange > INTERPTHRESHOLD; i++) {
- maxFractionalChange = iterateInterp2d(z, emptyPoints,
- correctionOvershoot(maxFractionalChange));
- }
- if(maxFractionalChange > INTERPTHRESHOLD) {
- Lib.log('interp2d didn\'t converge quickly', maxFractionalChange);
- }
-
- return z;
-};
-
-function iterateInterp2d(z, emptyPoints, overshoot) {
- var maxFractionalChange = 0;
- var thisPt;
- var i;
- var j;
- var p;
- var q;
- var neighborShift;
- var neighborRow;
- var neighborVal;
- var neighborCount;
- var neighborSum;
- var initialVal;
- var minNeighbor;
- var maxNeighbor;
-
- for(p = 0; p < emptyPoints.length; p++) {
- thisPt = emptyPoints[p];
- i = thisPt[0];
- j = thisPt[1];
- initialVal = z[i][j];
- neighborSum = 0;
- neighborCount = 0;
-
- for(q = 0; q < 4; q++) {
- neighborShift = NEIGHBORSHIFTS[q];
- neighborRow = z[i + neighborShift[0]];
- if(!neighborRow) continue;
- neighborVal = neighborRow[j + neighborShift[1]];
- if(neighborVal !== undefined) {
- if(neighborSum === 0) {
- minNeighbor = maxNeighbor = neighborVal;
- } else {
- minNeighbor = Math.min(minNeighbor, neighborVal);
- maxNeighbor = Math.max(maxNeighbor, neighborVal);
- }
- neighborCount++;
- neighborSum += neighborVal;
- }
- }
-
- if(neighborCount === 0) {
- throw 'iterateInterp2d order is wrong: no defined neighbors';
- }
-
- // this is the laplace equation interpolation:
- // each point is just the average of its neighbors
- // note that this ignores differential x/y scaling
- // which I think is the right approach, since we
- // don't know what that scaling means
- z[i][j] = neighborSum / neighborCount;
-
- if(initialVal === undefined) {
- if(neighborCount < 4) maxFractionalChange = 1;
- } else {
- // we can make large empty regions converge faster
- // if we overshoot the change vs the previous value
- z[i][j] = (1 + overshoot) * z[i][j] - overshoot * initialVal;
-
- if(maxNeighbor > minNeighbor) {
- maxFractionalChange = Math.max(maxFractionalChange,
- Math.abs(z[i][j] - initialVal) / (maxNeighbor - minNeighbor));
- }
- }
- }
-
- return maxFractionalChange;
-}
-
-},{"../../lib":168}],325:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Registry = _dereq_('../../registry');
-var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray;
-
-module.exports = function makeBoundArray(trace, arrayIn, v0In, dvIn, numbricks, ax) {
- var arrayOut = [];
- var isContour = Registry.traceIs(trace, 'contour');
- var isHist = Registry.traceIs(trace, 'histogram');
- var isGL2D = Registry.traceIs(trace, 'gl2d');
- var v0;
- var dv;
- var i;
-
- var isArrayOfTwoItemsOrMore = isArrayOrTypedArray(arrayIn) && arrayIn.length > 1;
-
- if(isArrayOfTwoItemsOrMore && !isHist && (ax.type !== 'category')) {
- var len = arrayIn.length;
-
- // given vals are brick centers
- // hopefully length === numbricks, but use this method even if too few are supplied
- // and extend it linearly based on the last two points
- if(len <= numbricks) {
- // contour plots only want the centers
- if(isContour || isGL2D) arrayOut = arrayIn.slice(0, numbricks);
- else if(numbricks === 1) {
- arrayOut = [arrayIn[0] - 0.5, arrayIn[0] + 0.5];
- } else {
- arrayOut = [1.5 * arrayIn[0] - 0.5 * arrayIn[1]];
-
- for(i = 1; i < len; i++) {
- arrayOut.push((arrayIn[i - 1] + arrayIn[i]) * 0.5);
- }
-
- arrayOut.push(1.5 * arrayIn[len - 1] - 0.5 * arrayIn[len - 2]);
- }
-
- if(len < numbricks) {
- var lastPt = arrayOut[arrayOut.length - 1];
- var delta = lastPt - arrayOut[arrayOut.length - 2];
-
- for(i = len; i < numbricks; i++) {
- lastPt += delta;
- arrayOut.push(lastPt);
- }
- }
- } else {
- // hopefully length === numbricks+1, but do something regardless:
- // given vals are brick boundaries
- return isContour ?
- arrayIn.slice(0, numbricks) : // we must be strict for contours
- arrayIn.slice(0, numbricks + 1);
- }
- } else {
- var calendar = trace[ax._id.charAt(0) + 'calendar'];
-
- if(isHist) {
- v0 = ax.r2c(v0In, 0, calendar);
- } else {
- if(isArrayOrTypedArray(arrayIn) && arrayIn.length === 1) {
- v0 = arrayIn[0];
- } else if(v0In === undefined) {
- v0 = 0;
- } else {
- var fn = ax.type === 'log' ? ax.d2c : ax.r2c;
- v0 = fn(v0In, 0, calendar);
- }
- }
-
- dv = dvIn || 1;
-
- for(i = (isContour || isGL2D) ? 0 : -0.5; i < numbricks; i++) {
- arrayOut.push(v0 + dv * i);
- }
- }
-
- return arrayOut;
-};
-
-},{"../../lib":168,"../../registry":256}],326:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var d3 = _dereq_('d3');
-var tinycolor = _dereq_('tinycolor2');
-
-var Registry = _dereq_('../../registry');
-var Lib = _dereq_('../../lib');
-var makeColorScaleFuncFromTrace = _dereq_('../../components/colorscale').makeColorScaleFuncFromTrace;
-var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces');
-
-module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
- var xa = plotinfo.xaxis;
- var ya = plotinfo.yaxis;
-
- Lib.makeTraceGroups(heatmapLayer, cdheatmaps, 'hm').each(function(cd) {
- var plotGroup = d3.select(this);
- var cd0 = cd[0];
- var trace = cd0.trace;
-
- var z = cd0.z;
- var x = cd0.x;
- var y = cd0.y;
- var xc = cd0.xCenter;
- var yc = cd0.yCenter;
- var isContour = Registry.traceIs(trace, 'contour');
- var zsmooth = isContour ? 'best' : trace.zsmooth;
-
- // get z dims
- var m = z.length;
- var n = Lib.maxRowLength(z);
- var xrev = false;
- var yrev = false;
-
- var left, right, temp, top, bottom, i;
-
- // TODO: if there are multiple overlapping categorical heatmaps,
- // or if we allow category sorting, then the categories may not be
- // sequential... may need to reorder and/or expand z
-
- // Get edges of png in pixels (xa.c2p() maps axes coordinates to pixel coordinates)
- // figure out if either axis is reversed (y is usually reversed, in pixel coords)
- // also clip the image to maximum 50% outside the visible plot area
- // bigger image lets you pan more naturally, but slows performance.
- // TODO: use low-resolution images outside the visible plot for panning
- // these while loops find the first and last brick bounds that are defined
- // (in case of log of a negative)
- i = 0;
- while(left === undefined && i < x.length - 1) {
- left = xa.c2p(x[i]);
- i++;
- }
- i = x.length - 1;
- while(right === undefined && i > 0) {
- right = xa.c2p(x[i]);
- i--;
- }
-
- if(right < left) {
- temp = right;
- right = left;
- left = temp;
- xrev = true;
- }
-
- i = 0;
- while(top === undefined && i < y.length - 1) {
- top = ya.c2p(y[i]);
- i++;
- }
- i = y.length - 1;
- while(bottom === undefined && i > 0) {
- bottom = ya.c2p(y[i]);
- i--;
- }
-
- if(bottom < top) {
- temp = top;
- top = bottom;
- bottom = temp;
- yrev = true;
- }
-
- // for contours with heatmap fill, we generate the boundaries based on
- // brick centers but then use the brick edges for drawing the bricks
- if(isContour) {
- xc = x;
- yc = y;
- x = cd0.xfill;
- y = cd0.yfill;
- }
-
- // make an image that goes at most half a screen off either side, to keep
- // time reasonable when you zoom in. if zsmooth is true/fast, don't worry
- // about this, because zooming doesn't increase number of pixels
- // if zsmooth is best, don't include anything off screen because it takes too long
- if(zsmooth !== 'fast') {
- var extra = zsmooth === 'best' ? 0 : 0.5;
- left = Math.max(-extra * xa._length, left);
- right = Math.min((1 + extra) * xa._length, right);
- top = Math.max(-extra * ya._length, top);
- bottom = Math.min((1 + extra) * ya._length, bottom);
- }
-
- var imageWidth = Math.round(right - left);
- var imageHeight = Math.round(bottom - top);
-
- // setup image nodes
-
- // if image is entirely off-screen, don't even draw it
- var isOffScreen = (imageWidth <= 0 || imageHeight <= 0);
-
- if(isOffScreen) {
- var noImage = plotGroup.selectAll('image').data([]);
- noImage.exit().remove();
- return;
- }
-
- // generate image data
-
- var canvasW, canvasH;
- if(zsmooth === 'fast') {
- canvasW = n;
- canvasH = m;
- } else {
- canvasW = imageWidth;
- canvasH = imageHeight;
- }
-
- var canvas = document.createElement('canvas');
- canvas.width = canvasW;
- canvas.height = canvasH;
- var context = canvas.getContext('2d');
-
- var sclFunc = makeColorScaleFuncFromTrace(trace, {noNumericCheck: true, returnArray: true});
-
- // map brick boundaries to image pixels
- var xpx,
- ypx;
- if(zsmooth === 'fast') {
- xpx = xrev ?
- function(index) { return n - 1 - index; } :
- Lib.identity;
- ypx = yrev ?
- function(index) { return m - 1 - index; } :
- Lib.identity;
- } else {
- xpx = function(index) {
- return Lib.constrain(Math.round(xa.c2p(x[index]) - left),
- 0, imageWidth);
- };
- ypx = function(index) {
- return Lib.constrain(Math.round(ya.c2p(y[index]) - top),
- 0, imageHeight);
- };
- }
-
- // build the pixel map brick-by-brick
- // cruise through z-matrix row-by-row
- // build a brick at each z-matrix value
- var yi = ypx(0);
- var yb = [yi, yi];
- var xbi = xrev ? 0 : 1;
- var ybi = yrev ? 0 : 1;
- // for collecting an average luminosity of the heatmap
- var pixcount = 0;
- var rcount = 0;
- var gcount = 0;
- var bcount = 0;
-
- var xb, j, xi, v, row, c;
-
- function setColor(v, pixsize) {
- if(v !== undefined) {
- var c = sclFunc(v);
- c[0] = Math.round(c[0]);
- c[1] = Math.round(c[1]);
- c[2] = Math.round(c[2]);
-
- pixcount += pixsize;
- rcount += c[0] * pixsize;
- gcount += c[1] * pixsize;
- bcount += c[2] * pixsize;
- return c;
- }
- return [0, 0, 0, 0];
- }
-
- function interpColor(r0, r1, xinterp, yinterp) {
- var z00 = r0[xinterp.bin0];
- if(z00 === undefined) return setColor(undefined, 1);
-
- var z01 = r0[xinterp.bin1];
- var z10 = r1[xinterp.bin0];
- var z11 = r1[xinterp.bin1];
- var dx = (z01 - z00) || 0;
- var dy = (z10 - z00) || 0;
- var dxy;
-
- // the bilinear interpolation term needs different calculations
- // for all the different permutations of missing data
- // among the neighbors of the main point, to ensure
- // continuity across brick boundaries.
- if(z01 === undefined) {
- if(z11 === undefined) dxy = 0;
- else if(z10 === undefined) dxy = 2 * (z11 - z00);
- else dxy = (2 * z11 - z10 - z00) * 2 / 3;
- } else if(z11 === undefined) {
- if(z10 === undefined) dxy = 0;
- else dxy = (2 * z00 - z01 - z10) * 2 / 3;
- } else if(z10 === undefined) dxy = (2 * z11 - z01 - z00) * 2 / 3;
- else dxy = (z11 + z00 - z01 - z10);
-
- return setColor(z00 + xinterp.frac * dx + yinterp.frac * (dy + xinterp.frac * dxy));
- }
-
- if(zsmooth) { // best or fast, works fastest with imageData
- var pxIndex = 0;
- var pixels;
-
- try {
- pixels = new Uint8Array(imageWidth * imageHeight * 4);
- } catch(e) {
- pixels = new Array(imageWidth * imageHeight * 4);
- }
-
- if(zsmooth === 'best') {
- var xForPx = xc || x;
- var yForPx = yc || y;
- var xPixArray = new Array(xForPx.length);
- var yPixArray = new Array(yForPx.length);
- var xinterpArray = new Array(imageWidth);
- var findInterpX = xc ? findInterpFromCenters : findInterp;
- var findInterpY = yc ? findInterpFromCenters : findInterp;
- var yinterp, r0, r1;
-
- // first make arrays of x and y pixel locations of brick boundaries
- for(i = 0; i < xForPx.length; i++) xPixArray[i] = Math.round(xa.c2p(xForPx[i]) - left);
- for(i = 0; i < yForPx.length; i++) yPixArray[i] = Math.round(ya.c2p(yForPx[i]) - top);
-
- // then make arrays of interpolations
- // (bin0=closest, bin1=next, frac=fractional dist.)
- for(i = 0; i < imageWidth; i++) xinterpArray[i] = findInterpX(i, xPixArray);
-
- // now do the interpolations and fill the png
- for(j = 0; j < imageHeight; j++) {
- yinterp = findInterpY(j, yPixArray);
- r0 = z[yinterp.bin0];
- r1 = z[yinterp.bin1];
- for(i = 0; i < imageWidth; i++, pxIndex += 4) {
- c = interpColor(r0, r1, xinterpArray[i], yinterp);
- putColor(pixels, pxIndex, c);
- }
- }
- } else { // zsmooth = fast
- for(j = 0; j < m; j++) {
- row = z[j];
- yb = ypx(j);
- for(i = 0; i < imageWidth; i++) {
- c = setColor(row[i], 1);
- pxIndex = (yb * imageWidth + xpx(i)) * 4;
- putColor(pixels, pxIndex, c);
- }
- }
- }
-
- var imageData = context.createImageData(imageWidth, imageHeight);
- try {
- imageData.data.set(pixels);
- } catch(e) {
- var pxArray = imageData.data;
- var dlen = pxArray.length;
- for(j = 0; j < dlen; j ++) {
- pxArray[j] = pixels[j];
- }
- }
-
- context.putImageData(imageData, 0, 0);
- } else { // zsmooth = false -> filling potentially large bricks works fastest with fillRect
- // gaps do not need to be exact integers, but if they *are* we will get
- // cleaner edges by rounding at least one edge
- var xGap = trace.xgap;
- var yGap = trace.ygap;
- var xGapLeft = Math.floor(xGap / 2);
- var yGapTop = Math.floor(yGap / 2);
-
- for(j = 0; j < m; j++) {
- row = z[j];
- yb.reverse();
- yb[ybi] = ypx(j + 1);
- if(yb[0] === yb[1] || yb[0] === undefined || yb[1] === undefined) {
- continue;
- }
- xi = xpx(0);
- xb = [xi, xi];
- for(i = 0; i < n; i++) {
- // build one color brick!
- xb.reverse();
- xb[xbi] = xpx(i + 1);
- if(xb[0] === xb[1] || xb[0] === undefined || xb[1] === undefined) {
- continue;
- }
- v = row[i];
- c = setColor(v, (xb[1] - xb[0]) * (yb[1] - yb[0]));
- context.fillStyle = 'rgba(' + c.join(',') + ')';
-
- context.fillRect(xb[0] + xGapLeft, yb[0] + yGapTop,
- xb[1] - xb[0] - xGap, yb[1] - yb[0] - yGap);
- }
- }
- }
-
- rcount = Math.round(rcount / pixcount);
- gcount = Math.round(gcount / pixcount);
- bcount = Math.round(bcount / pixcount);
- var avgColor = tinycolor('rgb(' + rcount + ',' + gcount + ',' + bcount + ')');
-
- gd._hmpixcount = (gd._hmpixcount||0) + pixcount;
- gd._hmlumcount = (gd._hmlumcount||0) + pixcount * avgColor.getLuminance();
-
- var image3 = plotGroup.selectAll('image')
- .data(cd);
-
- image3.enter().append('svg:image').attr({
- xmlns: xmlnsNamespaces.svg,
- preserveAspectRatio: 'none'
- });
-
- image3.attr({
- height: imageHeight,
- width: imageWidth,
- x: left,
- y: top,
- 'xlink:href': canvas.toDataURL('image/png')
- });
- });
-};
-
-// get interpolated bin value. Returns {bin0:closest bin, frac:fractional dist to next, bin1:next bin}
-function findInterp(pixel, pixArray) {
- var maxBin = pixArray.length - 2;
- var bin = Lib.constrain(Lib.findBin(pixel, pixArray), 0, maxBin);
- var pix0 = pixArray[bin];
- var pix1 = pixArray[bin + 1];
- var interp = Lib.constrain(bin + (pixel - pix0) / (pix1 - pix0) - 0.5, 0, maxBin);
- var bin0 = Math.round(interp);
- var frac = Math.abs(interp - bin0);
-
- if(!interp || interp === maxBin || !frac) {
- return {
- bin0: bin0,
- bin1: bin0,
- frac: 0
- };
- }
- return {
- bin0: bin0,
- frac: frac,
- bin1: Math.round(bin0 + frac / (interp - bin0))
- };
-}
-
-function findInterpFromCenters(pixel, centerPixArray) {
- var maxBin = centerPixArray.length - 1;
- var bin = Lib.constrain(Lib.findBin(pixel, centerPixArray), 0, maxBin);
- var pix0 = centerPixArray[bin];
- var pix1 = centerPixArray[bin + 1];
- var frac = ((pixel - pix0) / (pix1 - pix0)) || 0;
- if(frac <= 0) {
- return {
- bin0: bin,
- bin1: bin,
- frac: 0
- };
- }
- if(frac < 0.5) {
- return {
- bin0: bin,
- bin1: bin + 1,
- frac: frac
- };
- }
- return {
- bin0: bin + 1,
- bin1: bin,
- frac: 1 - frac
- };
-}
-
-function putColor(pixels, pxIndex, c) {
- pixels[pxIndex] = c[0];
- pixels[pxIndex + 1] = c[1];
- pixels[pxIndex + 2] = c[2];
- pixels[pxIndex + 3] = Math.round(c[3] * 255);
-}
-
-},{"../../components/colorscale":63,"../../constants/xmlns_namespaces":150,"../../lib":168,"../../registry":256,"d3":16,"tinycolor2":34}],327:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var d3 = _dereq_('d3');
-
-module.exports = function style(gd) {
- d3.select(gd).selectAll('.hm image')
- .style('opacity', function(d) {
- return d.trace.opacity;
- });
-};
-
-},{"d3":16}],328:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-module.exports = function handleStyleDefaults(traceIn, traceOut, coerce) {
- var zsmooth = coerce('zsmooth');
- if(zsmooth === false) {
- // ensure that xgap and ygap are coerced only when zsmooth allows them to have an effect.
- coerce('xgap');
- coerce('ygap');
- }
-
- coerce('zhoverformat');
-};
-
-},{}],329:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var isNumeric = _dereq_('fast-isnumeric');
-var Lib = _dereq_('../../lib');
-
-var Registry = _dereq_('../../registry');
-
-module.exports = function handleXYZDefaults(traceIn, traceOut, coerce, layout, xName, yName) {
- var z = coerce('z');
- xName = xName || 'x';
- yName = yName || 'y';
- var x, y;
-
- if(z === undefined || !z.length) return 0;
-
- if(Lib.isArray1D(traceIn.z)) {
- x = coerce(xName);
- y = coerce(yName);
-
- var xlen = Lib.minRowLength(x);
- var ylen = Lib.minRowLength(y);
-
- // column z must be accompanied by xName and yName arrays
- if(xlen === 0 || ylen === 0) return 0;
-
- traceOut._length = Math.min(xlen, ylen, z.length);
- } else {
- x = coordDefaults(xName, coerce);
- y = coordDefaults(yName, coerce);
-
- // TODO put z validation elsewhere
- if(!isValidZ(z)) return 0;
-
- coerce('transpose');
-
- traceOut._length = null;
- }
-
- var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults');
- handleCalendarDefaults(traceIn, traceOut, [xName, yName], layout);
-
- return true;
-};
-
-function coordDefaults(coordStr, coerce) {
- var coord = coerce(coordStr);
- var coordType = coord ? coerce(coordStr + 'type', 'array') : 'scaled';
-
- if(coordType === 'scaled') {
- coerce(coordStr + '0');
- coerce('d' + coordStr);
- }
-
- return coord;
-}
-
-function isValidZ(z) {
- var allRowsAreArrays = true;
- var oneRowIsFilled = false;
- var hasOneNumber = false;
- var zi;
-
- /*
- * Without this step:
- *
- * hasOneNumber = false breaks contour but not heatmap
- * allRowsAreArrays = false breaks contour but not heatmap
- * oneRowIsFilled = false breaks both
- */
-
- for(var i = 0; i < z.length; i++) {
- zi = z[i];
- if(!Lib.isArrayOrTypedArray(zi)) {
- allRowsAreArrays = false;
- break;
- }
- if(zi.length > 0) oneRowIsFilled = true;
- for(var j = 0; j < zi.length; j++) {
- if(isNumeric(zi[j])) {
- hasOneNumber = true;
- break;
- }
- }
- }
-
- return (allRowsAreArrays && oneRowIsFilled && hasOneNumber);
-}
-
-},{"../../lib":168,"../../registry":256,"fast-isnumeric":18}],330:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var barAttrs = _dereq_('../bar/attributes');
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
-var makeBinAttrs = _dereq_('./bin_attributes');
-var constants = _dereq_('./constants');
-var extendFlat = _dereq_('../../lib/extend').extendFlat;
-
-module.exports = {
- x: {
- valType: 'data_array',
- editType: 'calc+clearAxisTypes',
-
- },
- y: {
- valType: 'data_array',
- editType: 'calc+clearAxisTypes',
-
- },
-
- text: extendFlat({}, barAttrs.text, {
-
- }),
- hovertext: extendFlat({}, barAttrs.hovertext, {
-
- }),
- orientation: barAttrs.orientation,
-
- histfunc: {
- valType: 'enumerated',
- values: ['count', 'sum', 'avg', 'min', 'max'],
-
- dflt: 'count',
- editType: 'calc',
-
- },
- histnorm: {
- valType: 'enumerated',
- values: ['', 'percent', 'probability', 'density', 'probability density'],
- dflt: '',
-
- editType: 'calc',
-
- },
-
- cumulative: {
- enabled: {
- valType: 'boolean',
- dflt: false,
-
- editType: 'calc',
-
- },
-
- direction: {
- valType: 'enumerated',
- values: ['increasing', 'decreasing'],
- dflt: 'increasing',
-
- editType: 'calc',
-
- },
-
- currentbin: {
- valType: 'enumerated',
- values: ['include', 'exclude', 'half'],
- dflt: 'include',
-
- editType: 'calc',
-
- },
- editType: 'calc'
- },
- nbinsx: {
- valType: 'integer',
- min: 0,
- dflt: 0,
-
- editType: 'calc',
-
- },
- xbins: makeBinAttrs('x', true),
-
- nbinsy: {
- valType: 'integer',
- min: 0,
- dflt: 0,
-
- editType: 'calc',
-
- },
- ybins: makeBinAttrs('y', true),
- autobinx: {
- valType: 'boolean',
- dflt: null,
-
- editType: 'calc',
-
- },
- autobiny: {
- valType: 'boolean',
- dflt: null,
-
- editType: 'calc',
-
- },
-
- bingroup: {
- valType: 'string',
-
- dflt: '',
- editType: 'calc',
-
- },
-
- hovertemplate: hovertemplateAttrs({}, {
- keys: constants.eventDataKeys
- }),
-
- marker: barAttrs.marker,
-
- offsetgroup: barAttrs.offsetgroup,
- alignmentgroup: barAttrs.alignmentgroup,
-
- selected: barAttrs.selected,
- unselected: barAttrs.unselected,
-
- _deprecated: {
- bardir: barAttrs._deprecated.bardir
- }
-};
-
-},{"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../bar/attributes":266,"./bin_attributes":332,"./constants":336}],331:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-
-module.exports = function doAvg(size, counts) {
- var nMax = size.length;
- var total = 0;
- for(var i = 0; i < nMax; i++) {
- if(counts[i]) {
- size[i] /= counts[i];
- total += size[i];
- } else size[i] = null;
- }
- return total;
-};
-
-},{}],332:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = function makeBinAttrs(axLetter, match) {
- return {
- start: {
- valType: 'any', // for date axes
-
- editType: 'calc',
-
- },
- end: {
- valType: 'any', // for date axes
-
- editType: 'calc',
-
- },
- size: {
- valType: 'any', // for date axes
-
- editType: 'calc',
-
- },
- editType: 'calc'
- };
-};
-
-},{}],333:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var isNumeric = _dereq_('fast-isnumeric');
-
-
-module.exports = {
- count: function(n, i, size) {
- size[n]++;
- return 1;
- },
-
- sum: function(n, i, size, counterData) {
- var v = counterData[i];
- if(isNumeric(v)) {
- v = Number(v);
- size[n] += v;
- return v;
- }
- return 0;
- },
-
- avg: function(n, i, size, counterData, counts) {
- var v = counterData[i];
- if(isNumeric(v)) {
- v = Number(v);
- size[n] += v;
- counts[n]++;
- }
- return 0;
- },
-
- min: function(n, i, size, counterData) {
- var v = counterData[i];
- if(isNumeric(v)) {
- v = Number(v);
- if(!isNumeric(size[n])) {
- size[n] = v;
- return v;
- } else if(size[n] > v) {
- var delta = v - size[n];
- size[n] = v;
- return delta;
- }
- }
- return 0;
- },
-
- max: function(n, i, size, counterData) {
- var v = counterData[i];
- if(isNumeric(v)) {
- v = Number(v);
- if(!isNumeric(size[n])) {
- size[n] = v;
- return v;
- } else if(size[n] < v) {
- var delta = v - size[n];
- size[n] = v;
- return delta;
- }
- }
- return 0;
- }
-};
-
-},{"fast-isnumeric":18}],334:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var numConstants = _dereq_('../../constants/numerical');
-var oneYear = numConstants.ONEAVGYEAR;
-var oneMonth = numConstants.ONEAVGMONTH;
-var oneDay = numConstants.ONEDAY;
-var oneHour = numConstants.ONEHOUR;
-var oneMin = numConstants.ONEMIN;
-var oneSec = numConstants.ONESEC;
-var tickIncrement = _dereq_('../../plots/cartesian/axes').tickIncrement;
-
-
-/*
- * make a function that will find rounded bin edges
- * @param {number} leftGap: how far from the left edge of any bin is the closest data value?
- * @param {number} rightGap: how far from the right edge of any bin is the closest data value?
- * @param {Array[number]} binEdges: the actual edge values used in binning
- * @param {object} pa: the position axis
- * @param {string} calendar: the data calendar
- *
- * @return {function(v, isRightEdge)}:
- * find the start (isRightEdge is falsy) or end (truthy) label value for a bin edge `v`
- */
-module.exports = function getBinSpanLabelRound(leftGap, rightGap, binEdges, pa, calendar) {
- // the rounding digit is the largest digit that changes in *all* of 4 regions:
- // - inside the rightGap before binEdges[0] (shifted 10% to the left)
- // - inside the leftGap after binEdges[0] (expanded by 10% of rightGap on each end)
- // - same for binEdges[1]
- var dv0 = -1.1 * rightGap;
- var dv1 = -0.1 * rightGap;
- var dv2 = leftGap - dv1;
- var edge0 = binEdges[0];
- var edge1 = binEdges[1];
- var leftDigit = Math.min(
- biggestDigitChanged(edge0 + dv1, edge0 + dv2, pa, calendar),
- biggestDigitChanged(edge1 + dv1, edge1 + dv2, pa, calendar)
- );
- var rightDigit = Math.min(
- biggestDigitChanged(edge0 + dv0, edge0 + dv1, pa, calendar),
- biggestDigitChanged(edge1 + dv0, edge1 + dv1, pa, calendar)
- );
-
- // normally we try to make the label for the right edge different from
- // the left edge label, so it's unambiguous which bin gets data on the edge.
- // but if this results in more than 3 extra digits (or for dates, more than
- // 2 fields ie hr&min or min&sec, which is 3600x), it'll be more clutter than
- // useful so keep the label cleaner instead
- var digit, disambiguateEdges;
- if(leftDigit > rightDigit && rightDigit < Math.abs(edge1 - edge0) / 4000) {
- digit = leftDigit;
- disambiguateEdges = false;
- } else {
- digit = Math.min(leftDigit, rightDigit);
- disambiguateEdges = true;
- }
-
- if(pa.type === 'date' && digit > oneDay) {
- var dashExclude = (digit === oneYear) ? 1 : 6;
- var increment = (digit === oneYear) ? 'M12' : 'M1';
-
- return function(v, isRightEdge) {
- var dateStr = pa.c2d(v, oneYear, calendar);
- var dashPos = dateStr.indexOf('-', dashExclude);
- if(dashPos > 0) dateStr = dateStr.substr(0, dashPos);
- var roundedV = pa.d2c(dateStr, 0, calendar);
-
- if(roundedV < v) {
- var nextV = tickIncrement(roundedV, increment, false, calendar);
- if((roundedV + nextV) / 2 < v + leftGap) roundedV = nextV;
- }
-
- if(isRightEdge && disambiguateEdges) {
- return tickIncrement(roundedV, increment, true, calendar);
- }
-
- return roundedV;
- };
- }
-
- return function(v, isRightEdge) {
- var roundedV = digit * Math.round(v / digit);
- // if we rounded down and we could round up and still be < leftGap
- // (or what leftGap values round to), do that
- if(roundedV + (digit / 10) < v && roundedV + (digit * 0.9) < v + leftGap) {
- roundedV += digit;
- }
- // finally for the right edge back off one digit - but only if we can do that
- // and not clip off any data that's potentially in the bin
- if(isRightEdge && disambiguateEdges) {
- roundedV -= digit;
- }
- return roundedV;
- };
-};
-
-/*
- * Find the largest digit that changes within a (calcdata) region [v1, v2]
- * if dates, "digit" means date/time part when it's bigger than a second
- * returns the unit value to round to this digit, eg 0.01 to round to hundredths, or
- * 100 to round to hundreds. returns oneMonth or oneYear for month or year rounding,
- * so that Math.min will work, rather than 'M1' and 'M12'
- */
-function biggestDigitChanged(v1, v2, pa, calendar) {
- // are we crossing zero? can't say anything.
- // in principle this doesn't apply to dates but turns out this doesn't matter.
- if(v1 * v2 <= 0) return Infinity;
-
- var dv = Math.abs(v2 - v1);
- var isDate = pa.type === 'date';
- var digit = biggestGuaranteedDigitChanged(dv, isDate);
- // see if a larger digit also changed
- for(var i = 0; i < 10; i++) {
- // numbers: next digit needs to be >10x but <100x then gets rounded down.
- // dates: next digit can be as much as 60x (then rounded down)
- var nextDigit = biggestGuaranteedDigitChanged(digit * 80, isDate);
- // if we get to years, the chain stops
- if(digit === nextDigit) break;
- if(didDigitChange(nextDigit, v1, v2, isDate, pa, calendar)) digit = nextDigit;
- else break;
- }
- return digit;
-}
-
-/*
- * Find the largest digit that *definitely* changes in a region [v, v + dv] for any v
- * for nonuniform date regions (months/years) pick the largest
- */
-function biggestGuaranteedDigitChanged(dv, isDate) {
- if(isDate && dv > oneSec) {
- // this is supposed to be the biggest *guaranteed* change
- // so compare to the longest month and year across any calendar,
- // and we'll iterate back up later
- // note: does not support rounding larger than one year. We could add
- // that if anyone wants it, but seems unusual and not strictly necessary.
- if(dv > oneDay) {
- if(dv > oneYear * 1.1) return oneYear;
- if(dv > oneMonth * 1.1) return oneMonth;
- return oneDay;
- }
-
- if(dv > oneHour) return oneHour;
- if(dv > oneMin) return oneMin;
- return oneSec;
- }
- return Math.pow(10, Math.floor(Math.log(dv) / Math.LN10));
-}
-
-function didDigitChange(digit, v1, v2, isDate, pa, calendar) {
- if(isDate && digit > oneDay) {
- var dateParts1 = dateParts(v1, pa, calendar);
- var dateParts2 = dateParts(v2, pa, calendar);
- var parti = (digit === oneYear) ? 0 : 1;
- return dateParts1[parti] !== dateParts2[parti];
- }
- return Math.floor(v2 / digit) - Math.floor(v1 / digit) > 0.1;
-}
-
-function dateParts(v, pa, calendar) {
- var parts = pa.c2d(v, oneYear, calendar).split('-');
- if(parts[0] === '') {
- parts.unshift();
- parts[0] = '-' + parts[0];
- }
- return parts;
-}
-
-},{"../../constants/numerical":149,"../../plots/cartesian/axes":212}],335:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var isNumeric = _dereq_('fast-isnumeric');
-
-var Lib = _dereq_('../../lib');
-var Registry = _dereq_('../../registry');
-var Axes = _dereq_('../../plots/cartesian/axes');
-
-var arraysToCalcdata = _dereq_('../bar/arrays_to_calcdata');
-var binFunctions = _dereq_('./bin_functions');
-var normFunctions = _dereq_('./norm_functions');
-var doAvg = _dereq_('./average');
-var getBinSpanLabelRound = _dereq_('./bin_label_vals');
-
-function calc(gd, trace) {
- var pos = [];
- var size = [];
- var pa = Axes.getFromId(gd, trace.orientation === 'h' ? trace.yaxis : trace.xaxis);
- var mainData = trace.orientation === 'h' ? 'y' : 'x';
- var counterData = {x: 'y', y: 'x'}[mainData];
- var calendar = trace[mainData + 'calendar'];
- var cumulativeSpec = trace.cumulative;
- var i;
-
- var binsAndPos = calcAllAutoBins(gd, trace, pa, mainData);
- var binSpec = binsAndPos[0];
- var pos0 = binsAndPos[1];
-
- var nonuniformBins = typeof binSpec.size === 'string';
- var binEdges = [];
- var bins = nonuniformBins ? binEdges : binSpec;
- // make the empty bin array
- var inc = [];
- var counts = [];
- var inputPoints = [];
- var total = 0;
- var norm = trace.histnorm;
- var func = trace.histfunc;
- var densityNorm = norm.indexOf('density') !== -1;
- var i2, binEnd, n;
-
- if(cumulativeSpec.enabled && densityNorm) {
- // we treat "cumulative" like it means "integral" if you use a density norm,
- // which in the end means it's the same as without "density"
- norm = norm.replace(/ ?density$/, '');
- densityNorm = false;
- }
-
- var extremeFunc = func === 'max' || func === 'min';
- var sizeInit = extremeFunc ? null : 0;
- var binFunc = binFunctions.count;
- var normFunc = normFunctions[norm];
- var isAvg = false;
- var pr2c = function(v) { return pa.r2c(v, 0, calendar); };
- var rawCounterData;
-
- if(Lib.isArrayOrTypedArray(trace[counterData]) && func !== 'count') {
- rawCounterData = trace[counterData];
- isAvg = func === 'avg';
- binFunc = binFunctions[func];
- }
-
- // create the bins (and any extra arrays needed)
- // assume more than 1e6 bins is an error, so we don't crash the browser
- i = pr2c(binSpec.start);
-
- // decrease end a little in case of rounding errors
- binEnd = pr2c(binSpec.end) + (i - Axes.tickIncrement(i, binSpec.size, false, calendar)) / 1e6;
-
- while(i < binEnd && pos.length < 1e6) {
- i2 = Axes.tickIncrement(i, binSpec.size, false, calendar);
- pos.push((i + i2) / 2);
- size.push(sizeInit);
- inputPoints.push([]);
- // nonuniform bins (like months) we need to search,
- // rather than straight calculate the bin we're in
- binEdges.push(i);
- // nonuniform bins also need nonuniform normalization factors
- if(densityNorm) inc.push(1 / (i2 - i));
- if(isAvg) counts.push(0);
- // break to avoid infinite loops
- if(i2 <= i) break;
- i = i2;
- }
- binEdges.push(i);
-
- // for date axes we need bin bounds to be calcdata. For nonuniform bins
- // we already have this, but uniform with start/end/size they're still strings.
- if(!nonuniformBins && pa.type === 'date') {
- bins = {
- start: pr2c(bins.start),
- end: pr2c(bins.end),
- size: bins.size
- };
- }
-
- // bin the data
- // and make histogram-specific pt-number-to-cd-index map object
- var nMax = size.length;
- var uniqueValsPerBin = true;
- var leftGap = Infinity;
- var rightGap = Infinity;
- var ptNumber2cdIndex = {};
- for(i = 0; i < pos0.length; i++) {
- var posi = pos0[i];
- n = Lib.findBin(posi, bins);
- if(n >= 0 && n < nMax) {
- total += binFunc(n, i, size, rawCounterData, counts);
- if(uniqueValsPerBin && inputPoints[n].length && posi !== pos0[inputPoints[n][0]]) {
- uniqueValsPerBin = false;
- }
- inputPoints[n].push(i);
- ptNumber2cdIndex[i] = n;
-
- leftGap = Math.min(leftGap, posi - binEdges[n]);
- rightGap = Math.min(rightGap, binEdges[n + 1] - posi);
- }
- }
-
- var roundFn;
- if(!uniqueValsPerBin) {
- roundFn = getBinSpanLabelRound(leftGap, rightGap, binEdges, pa, calendar);
- }
-
- // average and/or normalize the data, if needed
- if(isAvg) total = doAvg(size, counts);
- if(normFunc) normFunc(size, total, inc);
-
- // after all normalization etc, now we can accumulate if desired
- if(cumulativeSpec.enabled) cdf(size, cumulativeSpec.direction, cumulativeSpec.currentbin);
-
- var seriesLen = Math.min(pos.length, size.length);
- var cd = [];
- var firstNonzero = 0;
- var lastNonzero = seriesLen - 1;
-
- // look for empty bins at the ends to remove, so autoscale omits them
- for(i = 0; i < seriesLen; i++) {
- if(size[i]) {
- firstNonzero = i;
- break;
- }
- }
- for(i = seriesLen - 1; i >= firstNonzero; i--) {
- if(size[i]) {
- lastNonzero = i;
- break;
- }
- }
-
- // create the "calculated data" to plot
- for(i = firstNonzero; i <= lastNonzero; i++) {
- if((isNumeric(pos[i]) && isNumeric(size[i]))) {
- var cdi = {
- p: pos[i],
- s: size[i],
- b: 0
- };
-
- // setup hover and event data fields,
- // N.B. pts and "hover" positions ph0/ph1 don't seem to make much sense
- // for cumulative distributions
- if(!cumulativeSpec.enabled) {
- cdi.pts = inputPoints[i];
- if(uniqueValsPerBin) {
- cdi.ph0 = cdi.ph1 = (inputPoints[i].length) ? pos0[inputPoints[i][0]] : pos[i];
- } else {
- cdi.ph0 = roundFn(binEdges[i]);
- cdi.ph1 = roundFn(binEdges[i + 1], true);
- }
- }
- cd.push(cdi);
- }
- }
-
- if(cd.length === 1) {
- // when we collapse to a single bin, calcdata no longer describes bin size
- // so we need to explicitly specify it
- cd[0].width1 = Axes.tickIncrement(cd[0].p, binSpec.size, false, calendar) - cd[0].p;
- }
-
- arraysToCalcdata(cd, trace);
-
- if(Lib.isArrayOrTypedArray(trace.selectedpoints)) {
- Lib.tagSelected(cd, trace, ptNumber2cdIndex);
- }
-
- return cd;
-}
-
-/*
- * calcAllAutoBins: we want all histograms inside the same bingroup
- * (see logic in Histogram.crossTraceDefaults) to share bin specs
- *
- * If the user has explicitly specified differing
- * bin specs, there's nothing we can do, but if possible we will try to use the
- * smallest bins of any of the auto values for all histograms inside the same
- * bingroup.
- */
-function calcAllAutoBins(gd, trace, pa, mainData, _overlayEdgeCase) {
- var binAttr = mainData + 'bins';
- var fullLayout = gd._fullLayout;
- var groupName = trace['_' + mainData + 'bingroup'];
- var binOpts = fullLayout._histogramBinOpts[groupName];
- var isOverlay = fullLayout.barmode === 'overlay';
- var i, traces, tracei, calendar, pos0, autoVals, cumulativeSpec;
-
- var r2c = function(v) { return pa.r2c(v, 0, calendar); };
- var c2r = function(v) { return pa.c2r(v, 0, calendar); };
-
- var cleanBound = pa.type === 'date' ?
- function(v) { return (v || v === 0) ? Lib.cleanDate(v, null, calendar) : null; } :
- function(v) { return isNumeric(v) ? Number(v) : null; };
-
- function setBound(attr, bins, newBins) {
- if(bins[attr + 'Found']) {
- bins[attr] = cleanBound(bins[attr]);
- if(bins[attr] === null) bins[attr] = newBins[attr];
- } else {
- autoVals[attr] = bins[attr] = newBins[attr];
- Lib.nestedProperty(traces[0], binAttr + '.' + attr).set(newBins[attr]);
- }
- }
-
- // all but the first trace in this group has already been marked finished
- // clear this flag, so next time we run calc we will run autobin again
- if(trace['_' + mainData + 'autoBinFinished']) {
- delete trace['_' + mainData + 'autoBinFinished'];
- } else {
- traces = binOpts.traces;
- var allPos = [];
-
- // Note: we're including `legendonly` traces here for autobin purposes,
- // so that showing & hiding from the legend won't affect bins.
- // But this complicates things a bit since those traces don't `calc`,
- // hence `isFirstVisible`.
- var isFirstVisible = true;
- var has2dMap = false;
- var hasHist2dContour = false;
- for(i = 0; i < traces.length; i++) {
- tracei = traces[i];
-
- if(tracei.visible) {
- var mainDatai = binOpts.dirs[i];
- pos0 = tracei['_' + mainDatai + 'pos0'] = pa.makeCalcdata(tracei, mainDatai);
-
- allPos = Lib.concat(allPos, pos0);
- delete tracei['_' + mainData + 'autoBinFinished'];
-
- if(trace.visible === true) {
- if(isFirstVisible) {
- isFirstVisible = false;
- } else {
- delete tracei._autoBin;
- tracei['_' + mainData + 'autoBinFinished'] = 1;
- }
- if(Registry.traceIs(tracei, '2dMap')) {
- has2dMap = true;
- }
- if(tracei.type === 'histogram2dcontour') {
- hasHist2dContour = true;
- }
- }
- }
- }
-
- calendar = traces[0][mainData + 'calendar'];
- var newBinSpec = Axes.autoBin(allPos, pa, binOpts.nbins, has2dMap, calendar, binOpts.sizeFound && binOpts.size);
-
- var autoBin = traces[0]._autoBin = {};
- autoVals = autoBin[binOpts.dirs[0]] = {};
-
- if(hasHist2dContour) {
- // the "true" 2nd argument reverses the tick direction (which we can't
- // just do with a minus sign because of month bins)
- if(!binOpts.size) {
- newBinSpec.start = c2r(Axes.tickIncrement(
- r2c(newBinSpec.start), newBinSpec.size, true, calendar));
- }
- if(binOpts.end === undefined) {
- newBinSpec.end = c2r(Axes.tickIncrement(
- r2c(newBinSpec.end), newBinSpec.size, false, calendar));
- }
- }
-
- // Edge case: single-valued histogram overlaying others
- // Use them all together to calculate the bin size for the single-valued one
- if(isOverlay && !Registry.traceIs(trace, '2dMap') && newBinSpec._dataSpan === 0 &&
- pa.type !== 'category' && pa.type !== 'multicategory') {
- // Several single-valued histograms! Stop infinite recursion,
- // just return an extra flag that tells handleSingleValueOverlays
- // to sort out this trace too
- if(_overlayEdgeCase) return [newBinSpec, pos0, true];
-
- newBinSpec = handleSingleValueOverlays(gd, trace, pa, mainData, binAttr);
- }
-
- // adjust for CDF edge cases
- cumulativeSpec = tracei.cumulative || {};
- if(cumulativeSpec.enabled && (cumulativeSpec.currentbin !== 'include')) {
- if(cumulativeSpec.direction === 'decreasing') {
- newBinSpec.start = c2r(Axes.tickIncrement(
- r2c(newBinSpec.start), newBinSpec.size, true, calendar));
- } else {
- newBinSpec.end = c2r(Axes.tickIncrement(
- r2c(newBinSpec.end), newBinSpec.size, false, calendar));
- }
- }
-
- binOpts.size = newBinSpec.size;
- if(!binOpts.sizeFound) {
- autoVals.size = newBinSpec.size;
- Lib.nestedProperty(traces[0], binAttr + '.size').set(newBinSpec.size);
- }
-
- setBound('start', binOpts, newBinSpec);
- setBound('end', binOpts, newBinSpec);
- }
-
- pos0 = trace['_' + mainData + 'pos0'];
- delete trace['_' + mainData + 'pos0'];
-
- // Each trace can specify its own start/end, or if omitted
- // we ensure they're beyond the bounds of this trace's data,
- // and we need to make sure start is aligned with the main start
- var traceInputBins = trace._input[binAttr] || {};
- var traceBinOptsCalc = Lib.extendFlat({}, binOpts);
- var mainStart = binOpts.start;
- var startIn = pa.r2l(traceInputBins.start);
- var hasStart = startIn !== undefined;
- if((binOpts.startFound || hasStart) && startIn !== pa.r2l(mainStart)) {
- // We have an explicit start to reconcile across traces
- // if this trace has an explicit start, shift it down to a bin edge
- // if another trace had an explicit start, shift it down to a
- // bin edge past our data
- var traceStart = hasStart ?
- startIn :
- Lib.aggNums(Math.min, null, pos0);
-
- var dummyAx = {
- type: (pa.type === 'category' || pa.type === 'multicategory') ? 'linear' : pa.type,
- r2l: pa.r2l,
- dtick: binOpts.size,
- tick0: mainStart,
- calendar: calendar,
- range: ([traceStart, Axes.tickIncrement(traceStart, binOpts.size, false, calendar)]).map(pa.l2r)
- };
- var newStart = Axes.tickFirst(dummyAx);
- if(newStart > pa.r2l(traceStart)) {
- newStart = Axes.tickIncrement(newStart, binOpts.size, true, calendar);
- }
- traceBinOptsCalc.start = pa.l2r(newStart);
- if(!hasStart) Lib.nestedProperty(trace, binAttr + '.start').set(traceBinOptsCalc.start);
- }
-
- var mainEnd = binOpts.end;
- var endIn = pa.r2l(traceInputBins.end);
- var hasEnd = endIn !== undefined;
- if((binOpts.endFound || hasEnd) && endIn !== pa.r2l(mainEnd)) {
- // Reconciling an explicit end is easier, as it doesn't need to
- // match bin edges
- var traceEnd = hasEnd ?
- endIn :
- Lib.aggNums(Math.max, null, pos0);
-
- traceBinOptsCalc.end = pa.l2r(traceEnd);
- if(!hasEnd) Lib.nestedProperty(trace, binAttr + '.start').set(traceBinOptsCalc.end);
- }
-
- // Backward compatibility for one-time autobinning.
- // autobin: true is handled in cleanData, but autobin: false
- // needs to be here where we have determined the values.
- var autoBinAttr = 'autobin' + mainData;
- if(trace._input[autoBinAttr] === false) {
- trace._input[binAttr] = Lib.extendFlat({}, trace[binAttr] || {});
- delete trace._input[autoBinAttr];
- delete trace[autoBinAttr];
- }
-
- return [traceBinOptsCalc, pos0];
-}
-
-/*
- * Adjust single-value histograms in overlay mode to make as good a
- * guess as we can at autobin values the user would like.
- *
- * Returns the binSpec for the trace that sparked all this
- */
-function handleSingleValueOverlays(gd, trace, pa, mainData, binAttr) {
- var fullLayout = gd._fullLayout;
- var overlaidTraceGroup = getConnectedHistograms(gd, trace);
- var pastThisTrace = false;
- var minSize = Infinity;
- var singleValuedTraces = [trace];
- var i, tracei, binOpts;
-
- // first collect all the:
- // - min bin size from all multi-valued traces
- // - single-valued traces
- for(i = 0; i < overlaidTraceGroup.length; i++) {
- tracei = overlaidTraceGroup[i];
-
- if(tracei === trace) {
- pastThisTrace = true;
- } else if(!pastThisTrace) {
- // This trace has already had its autobins calculated, so either:
- // - it is part of a bingroup
- // - it is NOT a single-valued trace
- binOpts = fullLayout._histogramBinOpts[tracei['_' + mainData + 'bingroup']];
- minSize = Math.min(minSize, binOpts.size || tracei[binAttr].size);
- } else {
- var resulti = calcAllAutoBins(gd, tracei, pa, mainData, true);
- var binSpeci = resulti[0];
- var isSingleValued = resulti[2];
-
- // so we can use this result when we get to tracei in the normal
- // course of events, mark it as done and put _pos0 back
- tracei['_' + mainData + 'autoBinFinished'] = 1;
- tracei['_' + mainData + 'pos0'] = resulti[1];
-
- if(isSingleValued) {
- singleValuedTraces.push(tracei);
- } else {
- minSize = Math.min(minSize, binSpeci.size);
- }
- }
- }
-
- // find the real data values for each single-valued trace
- // hunt through pos0 for the first valid value
- var dataVals = new Array(singleValuedTraces.length);
- for(i = 0; i < singleValuedTraces.length; i++) {
- var pos0 = singleValuedTraces[i]['_' + mainData + 'pos0'];
- for(var j = 0; j < pos0.length; j++) {
- if(pos0[j] !== undefined) {
- dataVals[i] = pos0[j];
- break;
- }
- }
- }
-
- // are ALL traces are single-valued? use the min difference between
- // all of their values (which defaults to 1 if there's still only one)
- if(!isFinite(minSize)) {
- minSize = Lib.distinctVals(dataVals).minDiff;
- }
-
- // now apply the min size we found to all single-valued traces
- for(i = 0; i < singleValuedTraces.length; i++) {
- tracei = singleValuedTraces[i];
- var calendar = tracei[mainData + 'calendar'];
-
- var newBins = {
- start: pa.c2r(dataVals[i] - minSize / 2, 0, calendar),
- end: pa.c2r(dataVals[i] + minSize / 2, 0, calendar),
- size: minSize
- };
-
- tracei._input[binAttr] = tracei[binAttr] = newBins;
-
- binOpts = fullLayout._histogramBinOpts[tracei['_' + mainData + 'bingroup']];
- if(binOpts) Lib.extendFlat(binOpts, newBins);
- }
-
- return trace[binAttr];
-}
-
-/*
- * Return an array of histograms that share axes and orientation.
- *
- * Only considers histograms. In principle we could include bars in a
- * similar way to how we do manually binned histograms, though this
- * would have tons of edge cases and value judgments to make.
- */
-function getConnectedHistograms(gd, trace) {
- var xid = trace.xaxis;
- var yid = trace.yaxis;
- var orientation = trace.orientation;
-
- var out = [];
- var fullData = gd._fullData;
- for(var i = 0; i < fullData.length; i++) {
- var tracei = fullData[i];
- if(tracei.type === 'histogram' &&
- tracei.visible === true &&
- tracei.orientation === orientation &&
- tracei.xaxis === xid && tracei.yaxis === yid
- ) {
- out.push(tracei);
- }
- }
-
- return out;
-}
-
-function cdf(size, direction, currentBin) {
- var i, vi, prevSum;
-
- function firstHalfPoint(i) {
- prevSum = size[i];
- size[i] /= 2;
- }
-
- function nextHalfPoint(i) {
- vi = size[i];
- size[i] = prevSum + vi / 2;
- prevSum += vi;
- }
-
- if(currentBin === 'half') {
- if(direction === 'increasing') {
- firstHalfPoint(0);
- for(i = 1; i < size.length; i++) {
- nextHalfPoint(i);
- }
- } else {
- firstHalfPoint(size.length - 1);
- for(i = size.length - 2; i >= 0; i--) {
- nextHalfPoint(i);
- }
- }
- } else if(direction === 'increasing') {
- for(i = 1; i < size.length; i++) {
- size[i] += size[i - 1];
- }
-
- // 'exclude' is identical to 'include' just shifted one bin over
- if(currentBin === 'exclude') {
- size.unshift(0);
- size.pop();
- }
- } else {
- for(i = size.length - 2; i >= 0; i--) {
- size[i] += size[i + 1];
- }
-
- if(currentBin === 'exclude') {
- size.push(0);
- size.shift();
- }
- }
-}
-
-module.exports = {
- calc: calc,
- calcAllAutoBins: calcAllAutoBins
-};
-
-},{"../../lib":168,"../../plots/cartesian/axes":212,"../../registry":256,"../bar/arrays_to_calcdata":265,"./average":331,"./bin_functions":333,"./bin_label_vals":334,"./norm_functions":342,"fast-isnumeric":18}],336:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-module.exports = {
- eventDataKeys: ['binNumber']
-};
-
-},{}],337:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var axisIds = _dereq_('../../plots/cartesian/axis_ids');
-
-var traceIs = _dereq_('../../registry').traceIs;
-var handleGroupingDefaults = _dereq_('../bar/defaults').handleGroupingDefaults;
-
-var nestedProperty = Lib.nestedProperty;
-var getAxisGroup = axisIds.getAxisGroup;
-
-var BINATTRS = [
- {aStr: {x: 'xbins.start', y: 'ybins.start'}, name: 'start'},
- {aStr: {x: 'xbins.end', y: 'ybins.end'}, name: 'end'},
- {aStr: {x: 'xbins.size', y: 'ybins.size'}, name: 'size'},
- {aStr: {x: 'nbinsx', y: 'nbinsy'}, name: 'nbins'}
-];
-
-var BINDIRECTIONS = ['x', 'y'];
-
-// handle bin attrs and relink auto-determined values so fullData is complete
-module.exports = function crossTraceDefaults(fullData, fullLayout) {
- var allBinOpts = fullLayout._histogramBinOpts = {};
- var histTraces = [];
- var mustMatchTracesLookup = {};
- var otherTracesList = [];
-
- var traceOut, traces, groupName, binDir;
- var i, j, k;
-
- function coerce(attr, dflt) {
- return Lib.coerce(traceOut._input, traceOut, traceOut._module.attributes, attr, dflt);
- }
-
- function orientation2binDir(traceOut) {
- return traceOut.orientation === 'v' ? 'x' : 'y';
- }
-
- function getAxisType(traceOut, binDir) {
- var ax = axisIds.getFromTrace({_fullLayout: fullLayout}, traceOut, binDir);
- return ax.type;
- }
-
- function fillBinOpts(traceOut, groupName, binDir) {
- // N.B. group traces that don't have a bingroup with themselves
- var fallbackGroupName = traceOut.uid + '__' + binDir;
- if(!groupName) groupName = fallbackGroupName;
-
- var axType = getAxisType(traceOut, binDir);
- var calendar = traceOut[binDir + 'calendar'];
- var binOpts = allBinOpts[groupName];
- var needsNewItem = true;
-
- if(binOpts) {
- if(axType === binOpts.axType && calendar === binOpts.calendar) {
- needsNewItem = false;
- binOpts.traces.push(traceOut);
- binOpts.dirs.push(binDir);
- } else {
- groupName = fallbackGroupName;
-
- if(axType !== binOpts.axType) {
- Lib.warn([
- 'Attempted to group the bins of trace', traceOut.index,
- 'set on a', 'type:' + axType, 'axis',
- 'with bins on', 'type:' + binOpts.axType, 'axis.'
- ].join(' '));
- }
- if(calendar !== binOpts.calendar) {
- // prohibit bingroup for traces using different calendar,
- // there's probably a way to make this work, but skip for now
- Lib.warn([
- 'Attempted to group the bins of trace', traceOut.index,
- 'set with a', calendar, 'calendar',
- 'with bins',
- (binOpts.calendar ? 'on a ' + binOpts.calendar + ' calendar' : 'w/o a set calendar')
- ].join(' '));
- }
- }
- }
-
- if(needsNewItem) {
- allBinOpts[groupName] = {
- traces: [traceOut],
- dirs: [binDir],
- axType: axType,
- calendar: traceOut[binDir + 'calendar'] || ''
- };
- }
- traceOut['_' + binDir + 'bingroup'] = groupName;
- }
-
- for(i = 0; i < fullData.length; i++) {
- traceOut = fullData[i];
-
- if(traceIs(traceOut, 'histogram')) {
- histTraces.push(traceOut);
-
- // TODO: this shouldn't be relinked as it's only used within calc
- // https://github.com/plotly/plotly.js/issues/749
- delete traceOut._xautoBinFinished;
- delete traceOut._yautoBinFinished;
-
- // N.B. need to coerce *alignmentgroup* before *bingroup*, as traces
- // in same alignmentgroup "have to match"
- if(!traceIs(traceOut, '2dMap')) {
- handleGroupingDefaults(traceOut._input, traceOut, fullLayout, coerce);
- }
- }
- }
-
- var alignmentOpts = fullLayout._alignmentOpts || {};
-
- // Look for traces that "have to match", that is:
- // - 1d histogram traces on the same subplot with same orientation under barmode:stack,
- // - 1d histogram traces on the same subplot with same orientation under barmode:group
- // - 1d histogram traces on the same position axis with the same orientation
- // and the same *alignmentgroup* (coerced under barmode:group)
- // - Once `stackgroup` gets implemented (see https://github.com/plotly/plotly.js/issues/3614),
- // traces within the same stackgroup will also "have to match"
- for(i = 0; i < histTraces.length; i++) {
- traceOut = histTraces[i];
- groupName = '';
-
- if(!traceIs(traceOut, '2dMap')) {
- binDir = orientation2binDir(traceOut);
-
- if(fullLayout.barmode === 'group' && traceOut.alignmentgroup) {
- var pa = traceOut[binDir + 'axis'];
- var aGroupId = getAxisGroup(fullLayout, pa) + traceOut.orientation;
- if((alignmentOpts[aGroupId] || {})[traceOut.alignmentgroup]) {
- groupName = aGroupId;
- }
- }
-
- if(!groupName && fullLayout.barmode !== 'overlay') {
- groupName = (
- getAxisGroup(fullLayout, traceOut.xaxis) +
- getAxisGroup(fullLayout, traceOut.yaxis) +
- orientation2binDir(traceOut)
- );
- }
- }
-
- if(groupName) {
- if(!mustMatchTracesLookup[groupName]) {
- mustMatchTracesLookup[groupName] = [];
- }
- mustMatchTracesLookup[groupName].push(traceOut);
- } else {
- otherTracesList.push(traceOut);
- }
- }
-
- // Setup binOpts for traces that have to match,
- // if the traces have a valid bingroup, use that
- // if not use axis+binDir groupName
- for(groupName in mustMatchTracesLookup) {
- traces = mustMatchTracesLookup[groupName];
-
- // no need to 'force' anything when a single
- // trace is detected as "must match"
- if(traces.length === 1) {
- otherTracesList.push(traces[0]);
- continue;
- }
-
- var binGroupFound = false;
- for(i = 0; i < traces.length; i++) {
- traceOut = traces[i];
- binGroupFound = coerce('bingroup');
- break;
- }
-
- groupName = binGroupFound || groupName;
-
- for(i = 0; i < traces.length; i++) {
- traceOut = traces[i];
- var bingroupIn = traceOut._input.bingroup;
- if(bingroupIn && bingroupIn !== groupName) {
- Lib.warn([
- 'Trace', traceOut.index, 'must match',
- 'within bingroup', groupName + '.',
- 'Ignoring its bingroup:', bingroupIn, 'setting.'
- ].join(' '));
- }
- traceOut.bingroup = groupName;
-
- // N.B. no need to worry about 2dMap case
- // (where both bin direction are set in each trace)
- // as 2dMap trace never "have to match"
- fillBinOpts(traceOut, groupName, orientation2binDir(traceOut));
- }
- }
-
- // setup binOpts for traces that can but don't have to match,
- // notice that these traces can be matched with traces that have to match
- for(i = 0; i < otherTracesList.length; i++) {
- traceOut = otherTracesList[i];
-
- var binGroup = coerce('bingroup');
-
- if(traceIs(traceOut, '2dMap')) {
- for(k = 0; k < 2; k++) {
- binDir = BINDIRECTIONS[k];
- var binGroupInDir = coerce(binDir + 'bingroup',
- binGroup ? binGroup + '__' + binDir : null
- );
- fillBinOpts(traceOut, binGroupInDir, binDir);
- }
- } else {
- fillBinOpts(traceOut, binGroup, orientation2binDir(traceOut));
- }
- }
-
- // coerce bin attrs!
- for(groupName in allBinOpts) {
- var binOpts = allBinOpts[groupName];
- traces = binOpts.traces;
-
- for(j = 0; j < BINATTRS.length; j++) {
- var attrSpec = BINATTRS[j];
- var attr = attrSpec.name;
- var aStr;
- var autoVals;
-
- // nbins(x|y) is moot if we have a size. This depends on
- // nbins coming after size in binAttrs.
- if(attr === 'nbins' && binOpts.sizeFound) continue;
-
- for(i = 0; i < traces.length; i++) {
- traceOut = traces[i];
- binDir = binOpts.dirs[i];
- aStr = attrSpec.aStr[binDir];
-
- if(nestedProperty(traceOut._input, aStr).get() !== undefined) {
- binOpts[attr] = coerce(aStr);
- binOpts[attr + 'Found'] = true;
- break;
- }
-
- autoVals = (traceOut._autoBin || {})[binDir] || {};
- if(autoVals[attr]) {
- // if this is the *first* autoval
- nestedProperty(traceOut, aStr).set(autoVals[attr]);
- }
- }
-
- // start and end we need to coerce anyway, after having collected the
- // first of each into binOpts, in case a trace wants to restrict its
- // data to a certain range
- if(attr === 'start' || attr === 'end') {
- for(; i < traces.length; i++) {
- traceOut = traces[i];
- if(traceOut['_' + binDir + 'bingroup']) {
- autoVals = (traceOut._autoBin || {})[binDir] || {};
- coerce(aStr, autoVals[attr]);
- }
- }
- }
-
- if(attr === 'nbins' && !binOpts.sizeFound && !binOpts.nbinsFound) {
- traceOut = traces[0];
- binOpts[attr] = coerce(aStr);
- }
- }
- }
-};
-
-},{"../../lib":168,"../../plots/cartesian/axis_ids":215,"../../registry":256,"../bar/defaults":270}],338:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Registry = _dereq_('../../registry');
-var Lib = _dereq_('../../lib');
-var Color = _dereq_('../../components/color');
-
-var handleStyleDefaults = _dereq_('../bar/style_defaults');
-var attributes = _dereq_('./attributes');
-
-module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
- function coerce(attr, dflt) {
- return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
- }
-
- var x = coerce('x');
- var y = coerce('y');
-
- var cumulative = coerce('cumulative.enabled');
- if(cumulative) {
- coerce('cumulative.direction');
- coerce('cumulative.currentbin');
- }
-
- coerce('text');
- coerce('hovertext');
- coerce('hovertemplate');
-
- var orientation = coerce('orientation', (y && !x) ? 'h' : 'v');
- var sampleLetter = orientation === 'v' ? 'x' : 'y';
- var aggLetter = orientation === 'v' ? 'y' : 'x';
-
- var len = (x && y) ?
- Math.min(Lib.minRowLength(x) && Lib.minRowLength(y)) :
- Lib.minRowLength(traceOut[sampleLetter] || []);
-
- if(!len) {
- traceOut.visible = false;
- return;
- }
-
- traceOut._length = len;
-
- var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults');
- handleCalendarDefaults(traceIn, traceOut, ['x', 'y'], layout);
-
- var hasAggregationData = traceOut[aggLetter];
- if(hasAggregationData) coerce('histfunc');
- coerce('histnorm');
-
- // Note: bin defaults are now handled in Histogram.crossTraceDefaults
- // autobin(x|y) are only included here to appease Plotly.validate
- coerce('autobin' + sampleLetter);
-
- handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout);
-
- Lib.coerceSelectionMarkerOpacity(traceOut, coerce);
-
- var lineColor = (traceOut.marker.line || {}).color;
-
- // override defaultColor for error bars with defaultLine
- var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults');
- errorBarsSupplyDefaults(traceIn, traceOut, lineColor || Color.defaultLine, {axis: 'y'});
- errorBarsSupplyDefaults(traceIn, traceOut, lineColor || Color.defaultLine, {axis: 'x', inherit: 'y'});
-};
-
-},{"../../components/color":51,"../../lib":168,"../../registry":256,"../bar/style_defaults":280,"./attributes":330}],339:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = function eventData(out, pt, trace, cd, pointNumber) {
- // standard cartesian event data
- out.x = 'xVal' in pt ? pt.xVal : pt.x;
- out.y = 'yVal' in pt ? pt.yVal : pt.y;
-
- // for 2d histograms
- if('zLabelVal' in pt) out.z = pt.zLabelVal;
-
- if(pt.xa) out.xaxis = pt.xa;
- if(pt.ya) out.yaxis = pt.ya;
-
- // specific to histogram - CDFs do not have pts (yet?)
- if(!(trace.cumulative || {}).enabled) {
- var pts = Array.isArray(pointNumber) ?
- cd[0].pts[pointNumber[0]][pointNumber[1]] :
- cd[pointNumber].pts;
-
- out.pointNumbers = pts;
- out.binNumber = out.pointNumber;
- delete out.pointNumber;
- delete out.pointIndex;
-
- var pointIndices;
- if(trace._indexToPoints) {
- pointIndices = [];
- for(var i = 0; i < pts.length; i++) {
- pointIndices = pointIndices.concat(trace._indexToPoints[pts[i]]);
- }
- } else {
- pointIndices = pts;
- }
-
- out.pointIndices = pointIndices;
- }
-
- return out;
-};
-
-},{}],340:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var barHover = _dereq_('../bar/hover').hoverPoints;
-var hoverLabelText = _dereq_('../../plots/cartesian/axes').hoverLabelText;
-
-module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
- var pts = barHover(pointData, xval, yval, hovermode);
-
- if(!pts) return;
-
- pointData = pts[0];
- var di = pointData.cd[pointData.index];
- var trace = pointData.cd[0].trace;
-
- if(!trace.cumulative.enabled) {
- var posLetter = trace.orientation === 'h' ? 'y' : 'x';
-
- pointData[posLetter + 'Label'] = hoverLabelText(pointData[posLetter + 'a'], di.ph0, di.ph1);
- }
-
- if(trace.hovermplate) pointData.hovertemplate = trace.hovertemplate;
-
- return pts;
-};
-
-},{"../../plots/cartesian/axes":212,"../bar/hover":272}],341:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-/**
- * Histogram has its own attribute, defaults and calc steps,
- * but uses bar's plot to display
- * and bar's crossTraceCalc (formerly known as setPositions) for stacking and grouping
- */
-
-/**
- * histogram errorBarsOK is debatable, but it's put in for backward compat.
- * there are use cases for it - sqrt for a simple histogram works right now,
- * constant and % work but they're not so meaningful. I guess it could be cool
- * to allow quadrature combination of errors in summed histograms...
- */
-
-module.exports = {
- attributes: _dereq_('./attributes'),
- layoutAttributes: _dereq_('../bar/layout_attributes'),
- supplyDefaults: _dereq_('./defaults'),
- crossTraceDefaults: _dereq_('./cross_trace_defaults'),
- supplyLayoutDefaults: _dereq_('../bar/layout_defaults'),
- calc: _dereq_('./calc').calc,
- crossTraceCalc: _dereq_('../bar/cross_trace_calc').crossTraceCalc,
- plot: _dereq_('../bar/plot').plot,
- layerName: 'barlayer',
- style: _dereq_('../bar/style').style,
- styleOnSelect: _dereq_('../bar/style').styleOnSelect,
- colorbar: _dereq_('../scatter/marker_colorbar'),
- hoverPoints: _dereq_('./hover'),
- selectPoints: _dereq_('../bar/select'),
- eventData: _dereq_('./event_data'),
-
- moduleType: 'trace',
- name: 'histogram',
- basePlotModule: _dereq_('../../plots/cartesian'),
- categories: ['bar-like', 'cartesian', 'svg', 'bar', 'histogram', 'oriented', 'errorBarsOK', 'showLegend'],
- meta: {
-
- }
-};
-
-},{"../../plots/cartesian":223,"../bar/cross_trace_calc":269,"../bar/layout_attributes":274,"../bar/layout_defaults":275,"../bar/plot":276,"../bar/select":277,"../bar/style":279,"../scatter/marker_colorbar":382,"./attributes":330,"./calc":335,"./cross_trace_defaults":337,"./defaults":338,"./event_data":339,"./hover":340}],342:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-
-module.exports = {
- percent: function(size, total) {
- var nMax = size.length;
- var norm = 100 / total;
- for(var n = 0; n < nMax; n++) size[n] *= norm;
- },
- probability: function(size, total) {
- var nMax = size.length;
- for(var n = 0; n < nMax; n++) size[n] /= total;
- },
- density: function(size, total, inc, yinc) {
- var nMax = size.length;
- yinc = yinc || 1;
- for(var n = 0; n < nMax; n++) size[n] *= inc[n] * yinc;
- },
- 'probability density': function(size, total, inc, yinc) {
- var nMax = size.length;
- if(yinc) total /= yinc;
- for(var n = 0; n < nMax; n++) size[n] *= inc[n] / total;
- }
-};
-
-},{}],343:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var histogramAttrs = _dereq_('../histogram/attributes');
-var makeBinAttrs = _dereq_('../histogram/bin_attributes');
-var heatmapAttrs = _dereq_('../heatmap/attributes');
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
-var colorScaleAttrs = _dereq_('../../components/colorscale/attributes');
-
-var extendFlat = _dereq_('../../lib/extend').extendFlat;
-
-module.exports = extendFlat(
- {
- x: histogramAttrs.x,
- y: histogramAttrs.y,
-
- z: {
- valType: 'data_array',
- editType: 'calc',
-
- },
- marker: {
- color: {
- valType: 'data_array',
- editType: 'calc',
-
- },
- editType: 'calc'
- },
-
- histnorm: histogramAttrs.histnorm,
- histfunc: histogramAttrs.histfunc,
- nbinsx: histogramAttrs.nbinsx,
- xbins: makeBinAttrs('x'),
- nbinsy: histogramAttrs.nbinsy,
- ybins: makeBinAttrs('y'),
- autobinx: histogramAttrs.autobinx,
- autobiny: histogramAttrs.autobiny,
-
- bingroup: extendFlat({}, histogramAttrs.bingroup, {
-
- }),
- xbingroup: extendFlat({}, histogramAttrs.bingroup, {
-
- }),
- ybingroup: extendFlat({}, histogramAttrs.bingroup, {
-
- }),
-
- xgap: heatmapAttrs.xgap,
- ygap: heatmapAttrs.ygap,
- zsmooth: heatmapAttrs.zsmooth,
- zhoverformat: heatmapAttrs.zhoverformat,
- hovertemplate: hovertemplateAttrs({}, {keys: 'z'})
- },
- colorScaleAttrs('', {cLetter: 'z', autoColorDflt: false})
-);
-
-},{"../../components/colorscale/attributes":58,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../heatmap/attributes":315,"../histogram/attributes":330,"../histogram/bin_attributes":332}],344:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var Axes = _dereq_('../../plots/cartesian/axes');
-
-var binFunctions = _dereq_('../histogram/bin_functions');
-var normFunctions = _dereq_('../histogram/norm_functions');
-var doAvg = _dereq_('../histogram/average');
-var getBinSpanLabelRound = _dereq_('../histogram/bin_label_vals');
-var calcAllAutoBins = _dereq_('../histogram/calc').calcAllAutoBins;
-
-module.exports = function calc(gd, trace) {
- var xa = Axes.getFromId(gd, trace.xaxis);
- var ya = Axes.getFromId(gd, trace.yaxis);
-
- var xcalendar = trace.xcalendar;
- var ycalendar = trace.ycalendar;
- var xr2c = function(v) { return xa.r2c(v, 0, xcalendar); };
- var yr2c = function(v) { return ya.r2c(v, 0, ycalendar); };
- var xc2r = function(v) { return xa.c2r(v, 0, xcalendar); };
- var yc2r = function(v) { return ya.c2r(v, 0, ycalendar); };
-
- var i, j, n, m;
-
- // calculate the bins
- var xBinsAndPos = calcAllAutoBins(gd, trace, xa, 'x');
- var xBinSpec = xBinsAndPos[0];
- var xPos0 = xBinsAndPos[1];
- var yBinsAndPos = calcAllAutoBins(gd, trace, ya, 'y');
- var yBinSpec = yBinsAndPos[0];
- var yPos0 = yBinsAndPos[1];
-
- var serieslen = trace._length;
- if(xPos0.length > serieslen) xPos0.splice(serieslen, xPos0.length - serieslen);
- if(yPos0.length > serieslen) yPos0.splice(serieslen, yPos0.length - serieslen);
-
- // make the empty bin array & scale the map
- var z = [];
- var onecol = [];
- var zerocol = [];
- var nonuniformBinsX = typeof xBinSpec.size === 'string';
- var nonuniformBinsY = typeof yBinSpec.size === 'string';
- var xEdges = [];
- var yEdges = [];
- var xbins = nonuniformBinsX ? xEdges : xBinSpec;
- var ybins = nonuniformBinsY ? yEdges : yBinSpec;
- var total = 0;
- var counts = [];
- var inputPoints = [];
- var norm = trace.histnorm;
- var func = trace.histfunc;
- var densitynorm = norm.indexOf('density') !== -1;
- var extremefunc = func === 'max' || func === 'min';
- var sizeinit = extremefunc ? null : 0;
- var binfunc = binFunctions.count;
- var normfunc = normFunctions[norm];
- var doavg = false;
- var xinc = [];
- var yinc = [];
-
- // set a binning function other than count?
- // for binning functions: check first for 'z',
- // then 'mc' in case we had a colored scatter plot
- // and want to transfer these colors to the 2D histo
- // TODO: axe this, make it the responsibility of the app changing type? or an impliedEdit?
- var rawCounterData = ('z' in trace) ?
- trace.z :
- (('marker' in trace && Array.isArray(trace.marker.color)) ?
- trace.marker.color : '');
- if(rawCounterData && func !== 'count') {
- doavg = func === 'avg';
- binfunc = binFunctions[func];
- }
-
- // decrease end a little in case of rounding errors
- var xBinSize = xBinSpec.size;
- var xBinStart = xr2c(xBinSpec.start);
- var xBinEnd = xr2c(xBinSpec.end) +
- (xBinStart - Axes.tickIncrement(xBinStart, xBinSize, false, xcalendar)) / 1e6;
-
- for(i = xBinStart; i < xBinEnd; i = Axes.tickIncrement(i, xBinSize, false, xcalendar)) {
- onecol.push(sizeinit);
- xEdges.push(i);
- if(doavg) zerocol.push(0);
- }
- xEdges.push(i);
-
- var nx = onecol.length;
- var dx = (i - xBinStart) / nx;
- var x0 = xc2r(xBinStart + dx / 2);
-
- var yBinSize = yBinSpec.size;
- var yBinStart = yr2c(yBinSpec.start);
- var yBinEnd = yr2c(yBinSpec.end) +
- (yBinStart - Axes.tickIncrement(yBinStart, yBinSize, false, ycalendar)) / 1e6;
-
- for(i = yBinStart; i < yBinEnd; i = Axes.tickIncrement(i, yBinSize, false, ycalendar)) {
- z.push(onecol.slice());
- yEdges.push(i);
- var ipCol = new Array(nx);
- for(j = 0; j < nx; j++) ipCol[j] = [];
- inputPoints.push(ipCol);
- if(doavg) counts.push(zerocol.slice());
- }
- yEdges.push(i);
-
- var ny = z.length;
- var dy = (i - yBinStart) / ny;
- var y0 = yc2r(yBinStart + dy / 2);
-
- if(densitynorm) {
- xinc = makeIncrements(onecol.length, xbins, dx, nonuniformBinsX);
- yinc = makeIncrements(z.length, ybins, dy, nonuniformBinsY);
- }
-
- // for date axes we need bin bounds to be calcdata. For nonuniform bins
- // we already have this, but uniform with start/end/size they're still strings.
- if(!nonuniformBinsX && xa.type === 'date') xbins = binsToCalc(xr2c, xbins);
- if(!nonuniformBinsY && ya.type === 'date') ybins = binsToCalc(yr2c, ybins);
-
- // put data into bins
- var uniqueValsPerX = true;
- var uniqueValsPerY = true;
- var xVals = new Array(nx);
- var yVals = new Array(ny);
- var xGapLow = Infinity;
- var xGapHigh = Infinity;
- var yGapLow = Infinity;
- var yGapHigh = Infinity;
- for(i = 0; i < serieslen; i++) {
- var xi = xPos0[i];
- var yi = yPos0[i];
- n = Lib.findBin(xi, xbins);
- m = Lib.findBin(yi, ybins);
- if(n >= 0 && n < nx && m >= 0 && m < ny) {
- total += binfunc(n, i, z[m], rawCounterData, counts[m]);
- inputPoints[m][n].push(i);
-
- if(uniqueValsPerX) {
- if(xVals[n] === undefined) xVals[n] = xi;
- else if(xVals[n] !== xi) uniqueValsPerX = false;
- }
- if(uniqueValsPerY) {
- if(yVals[m] === undefined) yVals[m] = yi;
- else if(yVals[m] !== yi) uniqueValsPerY = false;
- }
-
- xGapLow = Math.min(xGapLow, xi - xEdges[n]);
- xGapHigh = Math.min(xGapHigh, xEdges[n + 1] - xi);
- yGapLow = Math.min(yGapLow, yi - yEdges[m]);
- yGapHigh = Math.min(yGapHigh, yEdges[m + 1] - yi);
- }
- }
- // normalize, if needed
- if(doavg) {
- for(m = 0; m < ny; m++) total += doAvg(z[m], counts[m]);
- }
- if(normfunc) {
- for(m = 0; m < ny; m++) normfunc(z[m], total, xinc, yinc[m]);
- }
-
- return {
- x: xPos0,
- xRanges: getRanges(xEdges, uniqueValsPerX && xVals, xGapLow, xGapHigh, xa, xcalendar),
- x0: x0,
- dx: dx,
- y: yPos0,
- yRanges: getRanges(yEdges, uniqueValsPerY && yVals, yGapLow, yGapHigh, ya, ycalendar),
- y0: y0,
- dy: dy,
- z: z,
- pts: inputPoints
- };
-};
-
-function makeIncrements(len, bins, dv, nonuniform) {
- var out = new Array(len);
- var i;
- if(nonuniform) {
- for(i = 0; i < len; i++) out[i] = 1 / (bins[i + 1] - bins[i]);
- } else {
- var inc = 1 / dv;
- for(i = 0; i < len; i++) out[i] = inc;
- }
- return out;
-}
-
-function binsToCalc(r2c, bins) {
- return {
- start: r2c(bins.start),
- end: r2c(bins.end),
- size: bins.size
- };
-}
-
-function getRanges(edges, uniqueVals, gapLow, gapHigh, ax, calendar) {
- var i;
- var len = edges.length - 1;
- var out = new Array(len);
- var roundFn = getBinSpanLabelRound(gapLow, gapHigh, edges, ax, calendar);
-
- for(i = 0; i < len; i++) {
- var v = (uniqueVals || [])[i];
- out[i] = v === undefined ?
- [roundFn(edges[i]), roundFn(edges[i + 1], true)] :
- [v, v];
- }
- return out;
-}
-
-},{"../../lib":168,"../../plots/cartesian/axes":212,"../histogram/average":331,"../histogram/bin_functions":333,"../histogram/bin_label_vals":334,"../histogram/calc":335,"../histogram/norm_functions":342}],345:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-var handleSampleDefaults = _dereq_('./sample_defaults');
-var handleStyleDefaults = _dereq_('../heatmap/style_defaults');
-var colorscaleDefaults = _dereq_('../../components/colorscale/defaults');
-var attributes = _dereq_('./attributes');
-
-
-module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
- function coerce(attr, dflt) {
- return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
- }
-
- handleSampleDefaults(traceIn, traceOut, coerce, layout);
- if(traceOut.visible === false) return;
-
- handleStyleDefaults(traceIn, traceOut, coerce, layout);
- colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'});
- coerce('hovertemplate');
-};
-
-},{"../../components/colorscale/defaults":61,"../../lib":168,"../heatmap/style_defaults":328,"./attributes":343,"./sample_defaults":348}],346:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var heatmapHover = _dereq_('../heatmap/hover');
-var hoverLabelText = _dereq_('../../plots/cartesian/axes').hoverLabelText;
-
-module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLayer, contour) {
- var pts = heatmapHover(pointData, xval, yval, hovermode, hoverLayer, contour);
-
- if(!pts) return;
-
- pointData = pts[0];
- var indices = pointData.index;
- var ny = indices[0];
- var nx = indices[1];
- var cd0 = pointData.cd[0];
- var xRange = cd0.xRanges[nx];
- var yRange = cd0.yRanges[ny];
-
- pointData.xLabel = hoverLabelText(pointData.xa, xRange[0], xRange[1]);
- pointData.yLabel = hoverLabelText(pointData.ya, yRange[0], yRange[1]);
-
- return pts;
-};
-
-},{"../../plots/cartesian/axes":212,"../heatmap/hover":322}],347:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = {
-
- attributes: _dereq_('./attributes'),
- supplyDefaults: _dereq_('./defaults'),
- crossTraceDefaults: _dereq_('../histogram/cross_trace_defaults'),
- calc: _dereq_('../heatmap/calc'),
- plot: _dereq_('../heatmap/plot'),
- layerName: 'heatmaplayer',
- colorbar: _dereq_('../heatmap/colorbar'),
- style: _dereq_('../heatmap/style'),
- hoverPoints: _dereq_('./hover'),
- eventData: _dereq_('../histogram/event_data'),
-
- moduleType: 'trace',
- name: 'histogram2d',
- basePlotModule: _dereq_('../../plots/cartesian'),
- categories: ['cartesian', 'svg', '2dMap', 'histogram'],
- meta: {
-
-
- }
-};
-
-},{"../../plots/cartesian":223,"../heatmap/calc":316,"../heatmap/colorbar":318,"../heatmap/plot":326,"../heatmap/style":327,"../histogram/cross_trace_defaults":337,"../histogram/event_data":339,"./attributes":343,"./defaults":345,"./hover":346}],348:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Registry = _dereq_('../../registry');
-var Lib = _dereq_('../../lib');
-
-module.exports = function handleSampleDefaults(traceIn, traceOut, coerce, layout) {
- var x = coerce('x');
- var y = coerce('y');
- var xlen = Lib.minRowLength(x);
- var ylen = Lib.minRowLength(y);
-
- // we could try to accept x0 and dx, etc...
- // but that's a pretty weird use case.
- // for now require both x and y explicitly specified.
- if(!xlen || !ylen) {
- traceOut.visible = false;
- return;
- }
-
- traceOut._length = Math.min(xlen, ylen);
-
- var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults');
- handleCalendarDefaults(traceIn, traceOut, ['x', 'y'], layout);
-
- // if marker.color is an array, we can use it in aggregation instead of z
- var hasAggregationData = coerce('z') || coerce('marker.color');
-
- if(hasAggregationData) coerce('histfunc');
- coerce('histnorm');
-
- // Note: bin defaults are now handled in Histogram2D.crossTraceDefaults
- // autobin(x|y) are only included here to appease Plotly.validate
- coerce('autobinx');
- coerce('autobiny');
-};
-
-},{"../../lib":168,"../../registry":256}],349:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var histogram2dAttrs = _dereq_('../histogram2d/attributes');
-var contourAttrs = _dereq_('../contour/attributes');
-var colorScaleAttrs = _dereq_('../../components/colorscale/attributes');
-
-var extendFlat = _dereq_('../../lib/extend').extendFlat;
-
-module.exports = extendFlat({
- x: histogram2dAttrs.x,
- y: histogram2dAttrs.y,
- z: histogram2dAttrs.z,
- marker: histogram2dAttrs.marker,
-
- histnorm: histogram2dAttrs.histnorm,
- histfunc: histogram2dAttrs.histfunc,
- nbinsx: histogram2dAttrs.nbinsx,
- xbins: histogram2dAttrs.xbins,
- nbinsy: histogram2dAttrs.nbinsy,
- ybins: histogram2dAttrs.ybins,
- autobinx: histogram2dAttrs.autobinx,
- autobiny: histogram2dAttrs.autobiny,
-
- bingroup: histogram2dAttrs.bingroup,
- xbingroup: histogram2dAttrs.xbingroup,
- ybingroup: histogram2dAttrs.ybingroup,
-
- autocontour: contourAttrs.autocontour,
- ncontours: contourAttrs.ncontours,
- contours: contourAttrs.contours,
- line: contourAttrs.line,
- zhoverformat: histogram2dAttrs.zhoverformat,
- hovertemplate: histogram2dAttrs.hovertemplate
-},
- colorScaleAttrs('', {
- cLetter: 'z',
- editTypeOverride: 'calc'
- })
-);
-
-},{"../../components/colorscale/attributes":58,"../../lib/extend":162,"../contour/attributes":293,"../histogram2d/attributes":343}],350:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-var handleSampleDefaults = _dereq_('../histogram2d/sample_defaults');
-var handleContoursDefaults = _dereq_('../contour/contours_defaults');
-var handleStyleDefaults = _dereq_('../contour/style_defaults');
-var attributes = _dereq_('./attributes');
-
-
-module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
- function coerce(attr, dflt) {
- return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
- }
-
- function coerce2(attr) {
- return Lib.coerce2(traceIn, traceOut, attributes, attr);
- }
-
- handleSampleDefaults(traceIn, traceOut, coerce, layout);
- if(traceOut.visible === false) return;
-
- handleContoursDefaults(traceIn, traceOut, coerce, coerce2);
- handleStyleDefaults(traceIn, traceOut, coerce, layout);
- coerce('hovertemplate');
-};
-
-},{"../../lib":168,"../contour/contours_defaults":300,"../contour/style_defaults":314,"../histogram2d/sample_defaults":348,"./attributes":349}],351:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = {
- attributes: _dereq_('./attributes'),
- supplyDefaults: _dereq_('./defaults'),
- crossTraceDefaults: _dereq_('../histogram/cross_trace_defaults'),
- calc: _dereq_('../contour/calc'),
- plot: _dereq_('../contour/plot').plot,
- layerName: 'contourlayer',
- style: _dereq_('../contour/style'),
- colorbar: _dereq_('../contour/colorbar'),
- hoverPoints: _dereq_('../contour/hover'),
-
- moduleType: 'trace',
- name: 'histogram2dcontour',
- basePlotModule: _dereq_('../../plots/cartesian'),
- categories: ['cartesian', 'svg', '2dMap', 'contour', 'histogram', 'showLegend'],
- meta: {
-
-
- }
-};
-
-},{"../../plots/cartesian":223,"../contour/calc":294,"../contour/colorbar":296,"../contour/hover":306,"../contour/plot":311,"../contour/style":313,"../histogram/cross_trace_defaults":337,"./attributes":349,"./defaults":350}],352:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var plotAttrs = _dereq_('../../plots/attributes');
-var domainAttrs = _dereq_('../../plots/domain').attributes;
-var fontAttrs = _dereq_('../../plots/font_attributes');
-var colorAttrs = _dereq_('../../components/color/attributes');
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
-
-var extendFlat = _dereq_('../../lib/extend').extendFlat;
-
-var textFontAttrs = fontAttrs({
- editType: 'plot',
- arrayOk: true,
- colorEditType: 'plot',
-
-});
-
-module.exports = {
- labels: {
- valType: 'data_array',
- editType: 'calc',
-
- },
- // equivalent of x0 and dx, if label is missing
- label0: {
- valType: 'number',
-
- dflt: 0,
- editType: 'calc',
-
- },
- dlabel: {
- valType: 'number',
-
- dflt: 1,
- editType: 'calc',
-
- },
-
- values: {
- valType: 'data_array',
- editType: 'calc',
-
- },
-
- marker: {
- colors: {
- valType: 'data_array', // TODO 'color_array' ?
- editType: 'calc',
-
- },
-
- line: {
- color: {
- valType: 'color',
-
- dflt: colorAttrs.defaultLine,
- arrayOk: true,
- editType: 'style',
-
- },
- width: {
- valType: 'number',
-
- min: 0,
- dflt: 0,
- arrayOk: true,
- editType: 'style',
-
- },
- editType: 'calc'
- },
- editType: 'calc'
- },
-
- text: {
- valType: 'data_array',
- editType: 'calc',
-
- },
- hovertext: {
- valType: 'string',
-
- dflt: '',
- arrayOk: true,
- editType: 'style',
-
- },
-
-// 'see eg:'
-// 'https://www.e-education.psu.edu/natureofgeoinfo/sites/www.e-education.psu.edu.natureofgeoinfo/files/image/hisp_pies.gif',
-// '(this example involves a map too - may someday be a whole trace type',
-// 'of its own. but the point is the size of the whole pie is important.)'
- scalegroup: {
- valType: 'string',
-
- dflt: '',
- editType: 'calc',
-
- },
-
- // labels (legend is handled by plots.attributes.showlegend and layout.hiddenlabels)
- textinfo: {
- valType: 'flaglist',
-
- flags: ['label', 'text', 'value', 'percent'],
- extras: ['none'],
- editType: 'calc',
-
- },
- hoverinfo: extendFlat({}, plotAttrs.hoverinfo, {
- flags: ['label', 'text', 'value', 'percent', 'name']
- }),
- hovertemplate: hovertemplateAttrs({}, {
- keys: ['label', 'color', 'value', 'percent', 'text']
- }),
- textposition: {
- valType: 'enumerated',
-
- values: ['inside', 'outside', 'auto', 'none'],
- dflt: 'auto',
- arrayOk: true,
- editType: 'plot',
-
- },
- textfont: extendFlat({}, textFontAttrs, {
-
- }),
- insidetextfont: extendFlat({}, textFontAttrs, {
-
- }),
- outsidetextfont: extendFlat({}, textFontAttrs, {
-
- }),
-
- title: {
- text: {
- valType: 'string',
- dflt: '',
-
- editType: 'plot',
-
- },
- font: extendFlat({}, textFontAttrs, {
-
- }),
- position: {
- valType: 'enumerated',
- values: [
- 'top left', 'top center', 'top right',
- 'middle center',
- 'bottom left', 'bottom center', 'bottom right'
- ],
-
- editType: 'plot',
-
- },
-
- editType: 'plot'
- },
-
- // position and shape
- domain: domainAttrs({name: 'pie', trace: true, editType: 'calc'}),
-
- hole: {
- valType: 'number',
-
- min: 0,
- max: 1,
- dflt: 0,
- editType: 'calc',
-
- },
-
- // ordering and direction
- sort: {
- valType: 'boolean',
-
- dflt: true,
- editType: 'calc',
-
- },
- direction: {
- /**
- * there are two common conventions, both of which place the first
- * (largest, if sorted) slice with its left edge at 12 o'clock but
- * succeeding slices follow either cw or ccw from there.
- *
- * see http://visage.co/data-visualization-101-pie-charts/
- */
- valType: 'enumerated',
- values: ['clockwise', 'counterclockwise'],
-
- dflt: 'counterclockwise',
- editType: 'calc',
-
- },
- rotation: {
- valType: 'number',
-
- min: -360,
- max: 360,
- dflt: 0,
- editType: 'calc',
-
- },
-
- pull: {
- valType: 'number',
-
- min: 0,
- max: 1,
- dflt: 0,
- arrayOk: true,
- editType: 'calc',
-
- },
-
- _deprecated: {
- title: {
- valType: 'string',
- dflt: '',
-
- editType: 'calc',
-
- },
- titlefont: extendFlat({}, textFontAttrs, {
-
- }),
- titleposition: {
- valType: 'enumerated',
- values: [
- 'top left', 'top center', 'top right',
- 'middle center',
- 'bottom left', 'bottom center', 'bottom right'
- ],
-
- editType: 'calc',
-
- }
- }
-};
-
-},{"../../components/color/attributes":50,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../../plots/attributes":209,"../../plots/domain":237,"../../plots/font_attributes":238}],353:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Registry = _dereq_('../../registry');
-var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData;
-
-exports.name = 'pie';
-
-exports.plot = function(gd) {
- var Pie = Registry.getModule('pie');
- var cdPie = getModuleCalcData(gd.calcdata, Pie)[0];
- Pie.plot(gd, cdPie);
-};
-
-exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) {
- var hadPie = (oldFullLayout._has && oldFullLayout._has('pie'));
- var hasPie = (newFullLayout._has && newFullLayout._has('pie'));
-
- if(hadPie && !hasPie) {
- oldFullLayout._pielayer.selectAll('g.trace').remove();
- }
-};
-
-},{"../../plots/get_data":240,"../../registry":256}],354:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var isNumeric = _dereq_('fast-isnumeric');
-var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray;
-var tinycolor = _dereq_('tinycolor2');
-
-var Color = _dereq_('../../components/color');
-var helpers = _dereq_('./helpers');
-var isValidTextValue = _dereq_('../../lib').isValidTextValue;
-
-var extendedColorWayList = {};
-
-function calc(gd, trace) {
- var cd = [];
-
- var fullLayout = gd._fullLayout;
- var hiddenLabels = fullLayout.hiddenlabels || [];
-
- var labels = trace.labels;
- var colors = trace.marker.colors || [];
- var vals = trace.values;
- var hasVals = isArrayOrTypedArray(vals) && vals.length;
-
- var i, pt;
-
- if(trace.dlabel) {
- labels = new Array(vals.length);
- for(i = 0; i < vals.length; i++) {
- labels[i] = String(trace.label0 + i * trace.dlabel);
- }
- }
-
- var allThisTraceLabels = {};
- var pullColor = makePullColorFn(fullLayout['_' + trace.type + 'colormap']);
- var seriesLen = (hasVals ? vals : labels).length;
- var vTotal = 0;
- var isAggregated = false;
-
- for(i = 0; i < seriesLen; i++) {
- var v, label, hidden;
- if(hasVals) {
- v = vals[i];
- if(!isNumeric(v)) continue;
- v = +v;
- if(v < 0) continue;
- } else v = 1;
-
- label = labels[i];
- if(label === undefined || label === '') label = i;
- label = String(label);
-
- var thisLabelIndex = allThisTraceLabels[label];
- if(thisLabelIndex === undefined) {
- allThisTraceLabels[label] = cd.length;
-
- hidden = hiddenLabels.indexOf(label) !== -1;
-
- if(!hidden) vTotal += v;
-
- cd.push({
- v: v,
- label: label,
- color: pullColor(colors[i], label),
- i: i,
- pts: [i],
- hidden: hidden
- });
- } else {
- isAggregated = true;
-
- pt = cd[thisLabelIndex];
- pt.v += v;
- pt.pts.push(i);
- if(!pt.hidden) vTotal += v;
-
- if(pt.color === false && colors[i]) {
- pt.color = pullColor(colors[i], label);
- }
- }
- }
-
- var shouldSort = (trace.type === 'funnelarea') ? isAggregated : trace.sort;
- if(shouldSort) cd.sort(function(a, b) { return b.v - a.v; });
-
- // include the sum of all values in the first point
- if(cd[0]) cd[0].vTotal = vTotal;
-
- // now insert text
- var textinfo = trace.textinfo;
- if(textinfo && textinfo !== 'none') {
- var parts = textinfo.split('+');
- var hasFlag = function(flag) { return parts.indexOf(flag) !== -1; };
- var hasLabel = hasFlag('label');
- var hasText = hasFlag('text');
- var hasValue = hasFlag('value');
- var hasPercent = hasFlag('percent');
-
- var separators = fullLayout.separators;
- var text;
-
- for(i = 0; i < cd.length; i++) {
- pt = cd[i];
- text = hasLabel ? [pt.label] : [];
- if(hasText) {
- var tx = helpers.getFirstFilled(trace.text, pt.pts);
- if(isValidTextValue(tx)) text.push(tx);
- }
- if(hasValue) text.push(helpers.formatPieValue(pt.v, separators));
- if(hasPercent) text.push(helpers.formatPiePercent(pt.v / vTotal, separators));
- pt.text = text.join('
');
- }
- }
-
- return cd;
-}
-
-function makePullColorFn(colorMap) {
- return function pullColor(color, id) {
- if(!color) return false;
-
- color = tinycolor(color);
- if(!color.isValid()) return false;
-
- color = Color.addOpacity(color, color.getAlpha());
- if(!colorMap[id]) colorMap[id] = color;
-
- return color;
- };
-}
-
-/*
- * `calc` filled in (and collated) explicit colors.
- * Now we need to propagate these explicit colors to other traces,
- * and fill in default colors.
- * This is done after sorting, so we pick defaults
- * in the order slices will be displayed
- */
-function crossTraceCalc(gd, plotinfo) { // TODO: should we name the second argument opts?
- var desiredType = (plotinfo || {}).type;
- if(!desiredType) desiredType = 'pie';
-
- var fullLayout = gd._fullLayout;
- var calcdata = gd.calcdata;
- var colorWay = fullLayout[desiredType + 'colorway'];
- var colorMap = fullLayout['_' + desiredType + 'colormap'];
-
- if(fullLayout['extend' + desiredType + 'colors']) {
- colorWay = generateExtendedColors(colorWay, extendedColorWayList);
- }
- var dfltColorCount = 0;
-
- for(var i = 0; i < calcdata.length; i++) {
- var cd = calcdata[i];
- var traceType = cd[0].trace.type;
- if(traceType !== desiredType) continue;
-
- for(var j = 0; j < cd.length; j++) {
- var pt = cd[j];
- if(pt.color === false) {
- // have we seen this label and assigned a color to it in a previous trace?
- if(colorMap[pt.label]) {
- pt.color = colorMap[pt.label];
- } else {
- colorMap[pt.label] = pt.color = colorWay[dfltColorCount % colorWay.length];
- dfltColorCount++;
- }
- }
- }
- }
-}
-
-/**
- * pick a default color from the main default set, augmented by
- * itself lighter then darker before repeating
- */
-function generateExtendedColors(colorList, extendedColorWays) {
- var i;
- var colorString = JSON.stringify(colorList);
- var colors = extendedColorWays[colorString];
- if(!colors) {
- colors = colorList.slice();
-
- for(i = 0; i < colorList.length; i++) {
- colors.push(tinycolor(colorList[i]).lighten(20).toHexString());
- }
-
- for(i = 0; i < colorList.length; i++) {
- colors.push(tinycolor(colorList[i]).darken(20).toHexString());
- }
- extendedColorWays[colorString] = colors;
- }
-
- return colors;
-}
-
-module.exports = {
- calc: calc,
- crossTraceCalc: crossTraceCalc,
-
- makePullColorFn: makePullColorFn,
- generateExtendedColors: generateExtendedColors
-};
-
-},{"../../components/color":51,"../../lib":168,"./helpers":357,"fast-isnumeric":18,"tinycolor2":34}],355:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var attributes = _dereq_('./attributes');
-var handleDomainDefaults = _dereq_('../../plots/domain').defaults;
-var handleText = _dereq_('../bar/defaults').handleText;
-
-module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
- function coerce(attr, dflt) {
- return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
- }
-
- var len;
- var vals = coerce('values');
- var hasVals = Lib.isArrayOrTypedArray(vals);
- var labels = coerce('labels');
- if(Array.isArray(labels)) {
- len = labels.length;
- if(hasVals) len = Math.min(len, vals.length);
- } else if(hasVals) {
- len = vals.length;
-
- coerce('label0');
- coerce('dlabel');
- }
-
- if(!len) {
- traceOut.visible = false;
- return;
- }
- traceOut._length = len;
-
- var lineWidth = coerce('marker.line.width');
- if(lineWidth) coerce('marker.line.color');
-
- coerce('marker.colors');
-
- coerce('scalegroup');
- // TODO: hole needs to be coerced to the same value within a scaleegroup
-
- var textData = coerce('text');
- var textInfo = coerce('textinfo', Array.isArray(textData) ? 'text+percent' : 'percent');
- coerce('hovertext');
- coerce('hovertemplate');
-
- if(textInfo && textInfo !== 'none') {
- var textposition = coerce('textposition');
- handleText(traceIn, traceOut, layout, coerce, textposition, {
- moduleHasSelected: false,
- moduleHasUnselected: false,
- moduleHasConstrain: false,
- moduleHasCliponaxis: false,
- moduleHasTextangle: false,
- moduleHasInsideanchor: false
- });
- }
-
- handleDomainDefaults(traceOut, layout, coerce);
-
- var hole = coerce('hole');
- var title = coerce('title.text');
- if(title) {
- var titlePosition = coerce('title.position', hole ? 'middle center' : 'top center');
- if(!hole && titlePosition === 'middle center') traceOut.title.position = 'top center';
- Lib.coerceFont(coerce, 'title.font', layout.font);
- }
-
- coerce('sort');
- coerce('direction');
- coerce('rotation');
- coerce('pull');
-};
-
-},{"../../lib":168,"../../plots/domain":237,"../bar/defaults":270,"./attributes":352}],356:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var appendArrayMultiPointValues = _dereq_('../../components/fx/helpers').appendArrayMultiPointValues;
-
-// Note: like other eventData routines, this creates the data for hover/unhover/click events
-// but it has a different API and goes through a totally different pathway.
-// So to ensure it doesn't get misused, it's not attached to the Pie module.
-module.exports = function eventData(pt, trace) {
- var out = {
- curveNumber: trace.index,
- pointNumbers: pt.pts,
- data: trace._input,
- fullData: trace,
- label: pt.label,
- color: pt.color,
- value: pt.v,
- percent: pt.percent,
- text: pt.text,
-
- // pt.v (and pt.i below) for backward compatibility
- v: pt.v
- };
-
- // Only include pointNumber if it's unambiguous
- if(pt.pts.length === 1) out.pointNumber = out.i = pt.pts[0];
-
- // Add extra data arrays to the output
- // notice that this is the multi-point version ('s' on the end!)
- // so added data will be arrays matching the pointNumbers array.
- appendArrayMultiPointValues(out, trace, pt.pts);
-
- // don't include obsolete fields in new funnelarea traces
- if(trace.type === 'funnelarea') {
- delete out.v;
- delete out.i;
- }
-
- return out;
-};
-
-},{"../../components/fx/helpers":86}],357:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-exports.formatPiePercent = function formatPiePercent(v, separators) {
- var vRounded = (v * 100).toPrecision(3);
- if(vRounded.lastIndexOf('.') !== -1) {
- vRounded = vRounded.replace(/[.]?0+$/, '');
- }
- return Lib.numSeparate(vRounded, separators) + '%';
-};
-
-exports.formatPieValue = function formatPieValue(v, separators) {
- var vRounded = v.toPrecision(10);
- if(vRounded.lastIndexOf('.') !== -1) {
- vRounded = vRounded.replace(/[.]?0+$/, '');
- }
- return Lib.numSeparate(vRounded, separators);
-};
-
-exports.getFirstFilled = function getFirstFilled(array, indices) {
- if(!Array.isArray(array)) return;
- for(var i = 0; i < indices.length; i++) {
- var v = array[indices[i]];
- if(v || v === 0) return v;
- }
-};
-
-exports.castOption = function castOption(item, indices) {
- if(Array.isArray(item)) return exports.getFirstFilled(item, indices);
- else if(item) return item;
-};
-
-},{"../../lib":168}],358:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = {
- attributes: _dereq_('./attributes'),
- supplyDefaults: _dereq_('./defaults'),
- supplyLayoutDefaults: _dereq_('./layout_defaults'),
- layoutAttributes: _dereq_('./layout_attributes'),
-
- calc: _dereq_('./calc').calc,
- crossTraceCalc: _dereq_('./calc').crossTraceCalc,
-
- plot: _dereq_('./plot').plot,
- style: _dereq_('./style'),
- styleOne: _dereq_('./style_one'),
-
- moduleType: 'trace',
- name: 'pie',
- basePlotModule: _dereq_('./base_plot'),
- categories: ['pie-like', 'pie', 'showLegend'],
- meta: {
-
- }
-};
-
-},{"./attributes":352,"./base_plot":353,"./calc":354,"./defaults":355,"./layout_attributes":359,"./layout_defaults":360,"./plot":361,"./style":362,"./style_one":363}],359:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = {
- hiddenlabels: {
- valType: 'data_array',
-
- editType: 'calc',
-
- },
- piecolorway: {
- valType: 'colorlist',
-
- editType: 'calc',
-
- },
- extendpiecolors: {
- valType: 'boolean',
- dflt: true,
-
- editType: 'calc',
-
- }
-};
-
-},{}],360:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-var layoutAttributes = _dereq_('./layout_attributes');
-
-module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) {
- function coerce(attr, dflt) {
- return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt);
- }
-
- coerce('hiddenlabels');
- coerce('piecolorway', layoutOut.colorway);
- coerce('extendpiecolors');
-};
-
-},{"../../lib":168,"./layout_attributes":359}],361:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var d3 = _dereq_('d3');
-
-var Fx = _dereq_('../../components/fx');
-var Color = _dereq_('../../components/color');
-var Drawing = _dereq_('../../components/drawing');
-var Lib = _dereq_('../../lib');
-var svgTextUtils = _dereq_('../../lib/svg_text_utils');
-
-var helpers = _dereq_('./helpers');
-var eventData = _dereq_('./event_data');
-
-function plot(gd, cdModule) {
- var fullLayout = gd._fullLayout;
-
- prerenderTitles(cdModule, gd);
- layoutAreas(cdModule, fullLayout._size);
-
- var plotGroups = Lib.makeTraceGroups(fullLayout._pielayer, cdModule, 'trace').each(function(cd) {
- var plotGroup = d3.select(this);
- var cd0 = cd[0];
- var trace = cd0.trace;
-
- setCoords(cd);
-
- // TODO: miter might look better but can sometimes cause problems
- // maybe miter with a small-ish stroke-miterlimit?
- plotGroup.attr('stroke-linejoin', 'round');
-
- plotGroup.each(function() {
- var slices = d3.select(this).selectAll('g.slice').data(cd);
-
- slices.enter().append('g')
- .classed('slice', true);
- slices.exit().remove();
-
- var quadrants = [
- [[], []], // y<0: x<0, x>=0
- [[], []] // y>=0: x<0, x>=0
- ];
- var hasOutsideText = false;
-
- slices.each(function(pt) {
- if(pt.hidden) {
- d3.select(this).selectAll('path,g').remove();
- return;
- }
-
- // to have consistent event data compared to other traces
- pt.pointNumber = pt.i;
- pt.curveNumber = trace.index;
-
- quadrants[pt.pxmid[1] < 0 ? 0 : 1][pt.pxmid[0] < 0 ? 0 : 1].push(pt);
-
- var cx = cd0.cx;
- var cy = cd0.cy;
- var sliceTop = d3.select(this);
- var slicePath = sliceTop.selectAll('path.surface').data([pt]);
-
- slicePath.enter().append('path')
- .classed('surface', true)
- .style({'pointer-events': 'all'});
-
- sliceTop.call(attachFxHandlers, gd, cd);
-
- if(trace.pull) {
- var pull = +helpers.castOption(trace.pull, pt.pts) || 0;
- if(pull > 0) {
- cx += pull * pt.pxmid[0];
- cy += pull * pt.pxmid[1];
- }
- }
-
- pt.cxFinal = cx;
- pt.cyFinal = cy;
-
- function arc(start, finish, cw, scale) {
- var dx = scale * (finish[0] - start[0]);
- var dy = scale * (finish[1] - start[1]);
-
- return 'a' +
- (scale * cd0.r) + ',' + (scale * cd0.r) + ' 0 ' +
- pt.largeArc + (cw ? ' 1 ' : ' 0 ') + dx + ',' + dy;
- }
-
- var hole = trace.hole;
- if(pt.v === cd0.vTotal) { // 100% fails bcs arc start and end are identical
- var outerCircle = 'M' + (cx + pt.px0[0]) + ',' + (cy + pt.px0[1]) +
- arc(pt.px0, pt.pxmid, true, 1) +
- arc(pt.pxmid, pt.px0, true, 1) + 'Z';
- if(hole) {
- slicePath.attr('d',
- 'M' + (cx + hole * pt.px0[0]) + ',' + (cy + hole * pt.px0[1]) +
- arc(pt.px0, pt.pxmid, false, hole) +
- arc(pt.pxmid, pt.px0, false, hole) +
- 'Z' + outerCircle);
- } else slicePath.attr('d', outerCircle);
- } else {
- var outerArc = arc(pt.px0, pt.px1, true, 1);
-
- if(hole) {
- var rim = 1 - hole;
- slicePath.attr('d',
- 'M' + (cx + hole * pt.px1[0]) + ',' + (cy + hole * pt.px1[1]) +
- arc(pt.px1, pt.px0, false, hole) +
- 'l' + (rim * pt.px0[0]) + ',' + (rim * pt.px0[1]) +
- outerArc +
- 'Z');
- } else {
- slicePath.attr('d',
- 'M' + cx + ',' + cy +
- 'l' + pt.px0[0] + ',' + pt.px0[1] +
- outerArc +
- 'Z');
- }
- }
-
- // add text
- var textPosition = helpers.castOption(trace.textposition, pt.pts);
- var sliceTextGroup = sliceTop.selectAll('g.slicetext')
- .data(pt.text && (textPosition !== 'none') ? [0] : []);
-
- sliceTextGroup.enter().append('g')
- .classed('slicetext', true);
- sliceTextGroup.exit().remove();
-
- sliceTextGroup.each(function() {
- var sliceText = Lib.ensureSingle(d3.select(this), 'text', '', function(s) {
- // prohibit tex interpretation until we can handle
- // tex and regular text together
- s.attr('data-notex', 1);
- });
-
- sliceText.text(pt.text)
- .attr({
- 'class': 'slicetext',
- transform: '',
- 'text-anchor': 'middle'
- })
- .call(Drawing.font, textPosition === 'outside' ?
- determineOutsideTextFont(trace, pt, gd._fullLayout.font) :
- determineInsideTextFont(trace, pt, gd._fullLayout.font))
- .call(svgTextUtils.convertToTspans, gd);
-
- // position the text relative to the slice
- var textBB = Drawing.bBox(sliceText.node());
- var transform;
-
- if(textPosition === 'outside') {
- transform = transformOutsideText(textBB, pt);
- } else {
- transform = transformInsideText(textBB, pt, cd0);
- if(textPosition === 'auto' && transform.scale < 1) {
- sliceText.call(Drawing.font, trace.outsidetextfont);
- if(trace.outsidetextfont.family !== trace.insidetextfont.family ||
- trace.outsidetextfont.size !== trace.insidetextfont.size) {
- textBB = Drawing.bBox(sliceText.node());
- }
- transform = transformOutsideText(textBB, pt);
- }
- }
-
- var translateX = cx + pt.pxmid[0] * transform.rCenter + (transform.x || 0);
- var translateY = cy + pt.pxmid[1] * transform.rCenter + (transform.y || 0);
-
- // save some stuff to use later ensure no labels overlap
- if(transform.outside) {
- pt.yLabelMin = translateY - textBB.height / 2;
- pt.yLabelMid = translateY;
- pt.yLabelMax = translateY + textBB.height / 2;
- pt.labelExtraX = 0;
- pt.labelExtraY = 0;
- hasOutsideText = true;
- }
-
- sliceText.attr('transform',
- 'translate(' + translateX + ',' + translateY + ')' +
- (transform.scale < 1 ? ('scale(' + transform.scale + ')') : '') +
- (transform.rotate ? ('rotate(' + transform.rotate + ')') : '') +
- 'translate(' +
- (-(textBB.left + textBB.right) / 2) + ',' +
- (-(textBB.top + textBB.bottom) / 2) +
- ')');
- });
- });
-
- // add the title
- var titleTextGroup = d3.select(this).selectAll('g.titletext')
- .data(trace.title.text ? [0] : []);
-
- titleTextGroup.enter().append('g')
- .classed('titletext', true);
- titleTextGroup.exit().remove();
-
- titleTextGroup.each(function() {
- var titleText = Lib.ensureSingle(d3.select(this), 'text', '', function(s) {
- // prohibit tex interpretation as above
- s.attr('data-notex', 1);
- });
-
- var txt = trace.title.text;
- if(trace._meta) {
- txt = Lib.templateString(txt, trace._meta);
- }
-
- titleText.text(txt)
- .attr({
- 'class': 'titletext',
- transform: '',
- 'text-anchor': 'middle',
- })
- .call(Drawing.font, trace.title.font)
- .call(svgTextUtils.convertToTspans, gd);
-
- var transform;
-
- if(trace.title.position === 'middle center') {
- transform = positionTitleInside(cd0);
- } else {
- transform = positionTitleOutside(cd0, fullLayout._size);
- }
-
- titleText.attr('transform',
- 'translate(' + transform.x + ',' + transform.y + ')' +
- (transform.scale < 1 ? ('scale(' + transform.scale + ')') : '') +
- 'translate(' + transform.tx + ',' + transform.ty + ')');
- });
-
- // now make sure no labels overlap (at least within one pie)
- if(hasOutsideText) scootLabels(quadrants, trace);
-
- plotTextLines(slices, trace);
- });
- });
-
- // This is for a bug in Chrome (as of 2015-07-22, and does not affect FF)
- // if insidetextfont and outsidetextfont are different sizes, sometimes the size
- // of an "em" gets taken from the wrong element at first so lines are
- // spaced wrong. You just have to tell it to try again later and it gets fixed.
- // I have no idea why we haven't seen this in other contexts. Also, sometimes
- // it gets the initial draw correct but on redraw it gets confused.
- setTimeout(function() {
- plotGroups.selectAll('tspan').each(function() {
- var s = d3.select(this);
- if(s.attr('dy')) s.attr('dy', s.attr('dy'));
- });
- }, 0);
-}
-
-// TODO add support for transition
-function plotTextLines(slices, trace) {
- slices.each(function(pt) {
- var sliceTop = d3.select(this);
-
- if(!pt.labelExtraX && !pt.labelExtraY) {
- sliceTop.select('path.textline').remove();
- return;
- }
-
- // first move the text to its new location
- var sliceText = sliceTop.select('g.slicetext text');
-
- sliceText.attr('transform', 'translate(' + pt.labelExtraX + ',' + pt.labelExtraY + ')' +
- sliceText.attr('transform'));
-
- // then add a line to the new location
- var lineStartX = pt.cxFinal + pt.pxmid[0];
- var lineStartY = pt.cyFinal + pt.pxmid[1];
- var textLinePath = 'M' + lineStartX + ',' + lineStartY;
- var finalX = (pt.yLabelMax - pt.yLabelMin) * (pt.pxmid[0] < 0 ? -1 : 1) / 4;
-
- if(pt.labelExtraX) {
- var yFromX = pt.labelExtraX * pt.pxmid[1] / pt.pxmid[0];
- var yNet = pt.yLabelMid + pt.labelExtraY - (pt.cyFinal + pt.pxmid[1]);
-
- if(Math.abs(yFromX) > Math.abs(yNet)) {
- textLinePath +=
- 'l' + (yNet * pt.pxmid[0] / pt.pxmid[1]) + ',' + yNet +
- 'H' + (lineStartX + pt.labelExtraX + finalX);
- } else {
- textLinePath += 'l' + pt.labelExtraX + ',' + yFromX +
- 'v' + (yNet - yFromX) +
- 'h' + finalX;
- }
- } else {
- textLinePath +=
- 'V' + (pt.yLabelMid + pt.labelExtraY) +
- 'h' + finalX;
- }
-
- Lib.ensureSingle(sliceTop, 'path', 'textline')
- .call(Color.stroke, trace.outsidetextfont.color)
- .attr({
- 'stroke-width': Math.min(2, trace.outsidetextfont.size / 8),
- d: textLinePath,
- fill: 'none'
- });
- });
-}
-
-function attachFxHandlers(sliceTop, gd, cd) {
- var cd0 = cd[0];
- var trace = cd0.trace;
- var cx = cd0.cx;
- var cy = cd0.cy;
-
- // hover state vars
- // have we drawn a hover label, so it should be cleared later
- if(!('_hasHoverLabel' in trace)) trace._hasHoverLabel = false;
- // have we emitted a hover event, so later an unhover event should be emitted
- // note that click events do not depend on this - you can still get them
- // with hovermode: false or if you were earlier dragging, then clicked
- // in the same slice that you moused up in
- if(!('_hasHoverEvent' in trace)) trace._hasHoverEvent = false;
-
- sliceTop.on('mouseover', function(pt) {
- // in case fullLayout or fullData has changed without a replot
- var fullLayout2 = gd._fullLayout;
- var trace2 = gd._fullData[trace.index];
-
- if(gd._dragging || fullLayout2.hovermode === false) return;
-
- var hoverinfo = trace2.hoverinfo;
- if(Array.isArray(hoverinfo)) {
- // super hacky: we need to pull out the *first* hoverinfo from
- // pt.pts, then put it back into an array in a dummy trace
- // and call castHoverinfo on that.
- // TODO: do we want to have Fx.castHoverinfo somehow handle this?
- // it already takes an array for index, for 2D, so this seems tricky.
- hoverinfo = Fx.castHoverinfo({
- hoverinfo: [helpers.castOption(hoverinfo, pt.pts)],
- _module: trace._module
- }, fullLayout2, 0);
- }
-
- if(hoverinfo === 'all') hoverinfo = 'label+text+value+percent+name';
-
- // in case we dragged over the pie from another subplot,
- // or if hover is turned off
- if(trace2.hovertemplate || (hoverinfo !== 'none' && hoverinfo !== 'skip' && hoverinfo)) {
- var rInscribed = pt.rInscribed || 0;
- var hoverCenterX = cx + pt.pxmid[0] * (1 - rInscribed);
- var hoverCenterY = cy + pt.pxmid[1] * (1 - rInscribed);
- var separators = fullLayout2.separators;
- var text = [];
-
- if(hoverinfo && hoverinfo.indexOf('label') !== -1) text.push(pt.label);
- pt.text = helpers.castOption(trace2.hovertext || trace2.text, pt.pts);
- if(hoverinfo && hoverinfo.indexOf('text') !== -1) {
- var tx = pt.text;
- if(Lib.isValidTextValue(tx)) text.push(tx);
- }
- pt.value = pt.v;
- pt.valueLabel = helpers.formatPieValue(pt.v, separators);
- if(hoverinfo && hoverinfo.indexOf('value') !== -1) text.push(pt.valueLabel);
- pt.percent = pt.v / cd0.vTotal;
- pt.percentLabel = helpers.formatPiePercent(pt.percent, separators);
- if(hoverinfo && hoverinfo.indexOf('percent') !== -1) text.push(pt.percentLabel);
-
- var hoverLabel = trace2.hoverlabel;
- var hoverFont = hoverLabel.font;
-
- Fx.loneHover({
- trace: trace,
- x0: hoverCenterX - rInscribed * cd0.r,
- x1: hoverCenterX + rInscribed * cd0.r,
- y: hoverCenterY,
- text: text.join('
'),
- name: (trace2.hovertemplate || hoverinfo.indexOf('name') !== -1) ? trace2.name : undefined,
- idealAlign: pt.pxmid[0] < 0 ? 'left' : 'right',
- color: helpers.castOption(hoverLabel.bgcolor, pt.pts) || pt.color,
- borderColor: helpers.castOption(hoverLabel.bordercolor, pt.pts),
- fontFamily: helpers.castOption(hoverFont.family, pt.pts),
- fontSize: helpers.castOption(hoverFont.size, pt.pts),
- fontColor: helpers.castOption(hoverFont.color, pt.pts),
- nameLength: helpers.castOption(hoverLabel.namelength, pt.pts),
- textAlign: helpers.castOption(hoverLabel.align, pt.pts),
- hovertemplate: helpers.castOption(trace2.hovertemplate, pt.pts),
- hovertemplateLabels: pt,
- eventData: [eventData(pt, trace2)]
- }, {
- container: fullLayout2._hoverlayer.node(),
- outerContainer: fullLayout2._paper.node(),
- gd: gd
- });
-
- trace._hasHoverLabel = true;
- }
-
- trace._hasHoverEvent = true;
- gd.emit('plotly_hover', {
- points: [eventData(pt, trace2)],
- event: d3.event
- });
- });
-
- sliceTop.on('mouseout', function(evt) {
- var fullLayout2 = gd._fullLayout;
- var trace2 = gd._fullData[trace.index];
- var pt = d3.select(this).datum();
-
- if(trace._hasHoverEvent) {
- evt.originalEvent = d3.event;
- gd.emit('plotly_unhover', {
- points: [eventData(pt, trace2)],
- event: d3.event
- });
- trace._hasHoverEvent = false;
- }
-
- if(trace._hasHoverLabel) {
- Fx.loneUnhover(fullLayout2._hoverlayer.node());
- trace._hasHoverLabel = false;
- }
- });
-
- sliceTop.on('click', function(pt) {
- // TODO: this does not support right-click. If we want to support it, we
- // would likely need to change pie to use dragElement instead of straight
- // mapbox event binding. Or perhaps better, make a simple wrapper with the
- // right mousedown, mousemove, and mouseup handlers just for a left/right click
- // mapbox would use this too.
- var fullLayout2 = gd._fullLayout;
- var trace2 = gd._fullData[trace.index];
-
- if(gd._dragging || fullLayout2.hovermode === false) return;
-
- gd._hoverdata = [eventData(pt, trace2)];
- Fx.click(gd, d3.event);
- });
-}
-
-function determineOutsideTextFont(trace, pt, layoutFont) {
- var color =
- helpers.castOption(trace.outsidetextfont.color, pt.pts) ||
- helpers.castOption(trace.textfont.color, pt.pts) ||
- layoutFont.color;
-
- var family =
- helpers.castOption(trace.outsidetextfont.family, pt.pts) ||
- helpers.castOption(trace.textfont.family, pt.pts) ||
- layoutFont.family;
-
- var size =
- helpers.castOption(trace.outsidetextfont.size, pt.pts) ||
- helpers.castOption(trace.textfont.size, pt.pts) ||
- layoutFont.size;
-
- return {
- color: color,
- family: family,
- size: size
- };
-}
-
-function determineInsideTextFont(trace, pt, layoutFont) {
- var customColor = helpers.castOption(trace.insidetextfont.color, pt.pts);
- if(!customColor && trace._input.textfont) {
- // Why not simply using trace.textfont? Because if not set, it
- // defaults to layout.font which has a default color. But if
- // textfont.color and insidetextfont.color don't supply a value,
- // a contrasting color shall be used.
- customColor = helpers.castOption(trace._input.textfont.color, pt.pts);
- }
-
- var family =
- helpers.castOption(trace.insidetextfont.family, pt.pts) ||
- helpers.castOption(trace.textfont.family, pt.pts) ||
- layoutFont.family;
-
- var size =
- helpers.castOption(trace.insidetextfont.size, pt.pts) ||
- helpers.castOption(trace.textfont.size, pt.pts) ||
- layoutFont.size;
-
- return {
- color: customColor || Color.contrast(pt.color),
- family: family,
- size: size
- };
-}
-
-function prerenderTitles(cdModule, gd) {
- var cd0, trace;
-
- // Determine the width and height of the title for each pie.
- for(var i = 0; i < cdModule.length; i++) {
- cd0 = cdModule[i][0];
- trace = cd0.trace;
-
- if(trace.title.text) {
- var txt = trace.title.text;
- if(trace._meta) {
- txt = Lib.templateString(txt, trace._meta);
- }
-
- var dummyTitle = Drawing.tester.append('text')
- .attr('data-notex', 1)
- .text(txt)
- .call(Drawing.font, trace.title.font)
- .call(svgTextUtils.convertToTspans, gd);
- var bBox = Drawing.bBox(dummyTitle.node(), true);
- cd0.titleBox = {
- width: bBox.width,
- height: bBox.height,
- };
- dummyTitle.remove();
- }
- }
-}
-
-function transformInsideText(textBB, pt, cd0) {
- var textDiameter = Math.sqrt(textBB.width * textBB.width + textBB.height * textBB.height);
- var textAspect = textBB.width / textBB.height;
- var halfAngle = pt.halfangle;
- var ring = pt.ring;
- var rInscribed = pt.rInscribed;
- var r = cd0.r || pt.rpx1;
-
- // max size text can be inserted inside without rotating it
- // this inscribes the text rectangle in a circle, which is then inscribed
- // in the slice, so it will be an underestimate, which some day we may want
- // to improve so this case can get more use
- var transform = {
- scale: rInscribed * r * 2 / textDiameter,
-
- // and the center position and rotation in this case
- rCenter: 1 - rInscribed,
- rotate: 0
- };
-
- if(transform.scale >= 1) return transform;
-
- // max size if text is rotated radially
- var Qr = textAspect + 1 / (2 * Math.tan(halfAngle));
- var maxHalfHeightRotRadial = r * Math.min(
- 1 / (Math.sqrt(Qr * Qr + 0.5) + Qr),
- ring / (Math.sqrt(textAspect * textAspect + ring / 2) + textAspect)
- );
- var radialTransform = {
- scale: maxHalfHeightRotRadial * 2 / textBB.height,
- rCenter: Math.cos(maxHalfHeightRotRadial / r) -
- maxHalfHeightRotRadial * textAspect / r,
- rotate: (180 / Math.PI * pt.midangle + 720) % 180 - 90
- };
-
- // max size if text is rotated tangentially
- var aspectInv = 1 / textAspect;
- var Qt = aspectInv + 1 / (2 * Math.tan(halfAngle));
- var maxHalfWidthTangential = r * Math.min(
- 1 / (Math.sqrt(Qt * Qt + 0.5) + Qt),
- ring / (Math.sqrt(aspectInv * aspectInv + ring / 2) + aspectInv)
- );
- var tangentialTransform = {
- scale: maxHalfWidthTangential * 2 / textBB.width,
- rCenter: Math.cos(maxHalfWidthTangential / r) -
- maxHalfWidthTangential / textAspect / r,
- rotate: (180 / Math.PI * pt.midangle + 810) % 180 - 90
- };
- // if we need a rotated transform, pick the biggest one
- // even if both are bigger than 1
- var rotatedTransform = tangentialTransform.scale > radialTransform.scale ?
- tangentialTransform : radialTransform;
-
- if(transform.scale < 1 && rotatedTransform.scale > transform.scale) return rotatedTransform;
- return transform;
-}
-
-function getInscribedRadiusFraction(pt, cd0) {
- if(pt.v === cd0.vTotal && !cd0.trace.hole) return 1;// special case of 100% with no hole
-
- return Math.min(1 / (1 + 1 / Math.sin(pt.halfangle)), pt.ring / 2);
-}
-
-function transformOutsideText(textBB, pt) {
- var x = pt.pxmid[0];
- var y = pt.pxmid[1];
- var dx = textBB.width / 2;
- var dy = textBB.height / 2;
-
- if(x < 0) dx *= -1;
- if(y < 0) dy *= -1;
-
- return {
- scale: 1,
- rCenter: 1,
- rotate: 0,
- x: dx + Math.abs(dy) * (dx > 0 ? 1 : -1) / 2,
- y: dy / (1 + x * x / (y * y)),
- outside: true
- };
-}
-
-function positionTitleInside(cd0) {
- var textDiameter =
- Math.sqrt(cd0.titleBox.width * cd0.titleBox.width + cd0.titleBox.height * cd0.titleBox.height);
- return {
- x: cd0.cx,
- y: cd0.cy,
- scale: cd0.trace.hole * cd0.r * 2 / textDiameter,
- tx: 0,
- ty: - cd0.titleBox.height / 2 + cd0.trace.title.font.size
- };
-}
-
-function positionTitleOutside(cd0, plotSize) {
- var scaleX = 1;
- var scaleY = 1;
- var maxPull;
-
- var trace = cd0.trace;
- // position of the baseline point of the text box in the plot, before scaling.
- // we anchored the text in the middle, so the baseline is on the bottom middle
- // of the first line of text.
- var topMiddle = {
- x: cd0.cx,
- y: cd0.cy
- };
- // relative translation of the text box after scaling
- var translate = {
- tx: 0,
- ty: 0
- };
-
- // we reason below as if the baseline is the top middle point of the text box.
- // so we must add the font size to approximate the y-coord. of the top.
- // note that this correction must happen after scaling.
- translate.ty += trace.title.font.size;
- maxPull = getMaxPull(trace);
-
- if(trace.title.position.indexOf('top') !== -1) {
- topMiddle.y -= (1 + maxPull) * cd0.r;
- translate.ty -= cd0.titleBox.height;
- } else if(trace.title.position.indexOf('bottom') !== -1) {
- topMiddle.y += (1 + maxPull) * cd0.r;
- }
-
- var rx = applyAspectRatio(cd0.r, cd0.trace.aspectratio);
-
- var maxWidth = plotSize.w * (trace.domain.x[1] - trace.domain.x[0]) / 2;
- if(trace.title.position.indexOf('left') !== -1) {
- // we start the text at the left edge of the pie
- maxWidth = maxWidth + rx;
- topMiddle.x -= (1 + maxPull) * rx;
- translate.tx += cd0.titleBox.width / 2;
- } else if(trace.title.position.indexOf('center') !== -1) {
- maxWidth *= 2;
- } else if(trace.title.position.indexOf('right') !== -1) {
- maxWidth = maxWidth + rx;
- topMiddle.x += (1 + maxPull) * rx;
- translate.tx -= cd0.titleBox.width / 2;
- }
- scaleX = maxWidth / cd0.titleBox.width;
- scaleY = getTitleSpace(cd0, plotSize) / cd0.titleBox.height;
- return {
- x: topMiddle.x,
- y: topMiddle.y,
- scale: Math.min(scaleX, scaleY),
- tx: translate.tx,
- ty: translate.ty
- };
-}
-
-function applyAspectRatio(x, aspectratio) {
- return x / ((aspectratio === undefined) ? 1 : aspectratio);
-}
-
-function getTitleSpace(cd0, plotSize) {
- var trace = cd0.trace;
- var pieBoxHeight = plotSize.h * (trace.domain.y[1] - trace.domain.y[0]);
- // use at most half of the plot for the title
- return Math.min(cd0.titleBox.height, pieBoxHeight / 2);
-}
-
-function getMaxPull(trace) {
- var maxPull = trace.pull;
- if(!maxPull) return 0;
-
- var j;
- if(Array.isArray(maxPull)) {
- maxPull = 0;
- for(j = 0; j < trace.pull.length; j++) {
- if(trace.pull[j] > maxPull) maxPull = trace.pull[j];
- }
- }
- return maxPull;
-}
-
-function scootLabels(quadrants, trace) {
- var xHalf, yHalf, equatorFirst, farthestX, farthestY,
- xDiffSign, yDiffSign, thisQuad, oppositeQuad,
- wholeSide, i, thisQuadOutside, firstOppositeOutsidePt;
-
- function topFirst(a, b) { return a.pxmid[1] - b.pxmid[1]; }
- function bottomFirst(a, b) { return b.pxmid[1] - a.pxmid[1]; }
-
- function scootOneLabel(thisPt, prevPt) {
- if(!prevPt) prevPt = {};
-
- var prevOuterY = prevPt.labelExtraY + (yHalf ? prevPt.yLabelMax : prevPt.yLabelMin);
- var thisInnerY = yHalf ? thisPt.yLabelMin : thisPt.yLabelMax;
- var thisOuterY = yHalf ? thisPt.yLabelMax : thisPt.yLabelMin;
- var thisSliceOuterY = thisPt.cyFinal + farthestY(thisPt.px0[1], thisPt.px1[1]);
- var newExtraY = prevOuterY - thisInnerY;
-
- var xBuffer, i, otherPt, otherOuterY, otherOuterX, newExtraX;
-
- // make sure this label doesn't overlap other labels
- // this *only* has us move these labels vertically
- if(newExtraY * yDiffSign > 0) thisPt.labelExtraY = newExtraY;
-
- // make sure this label doesn't overlap any slices
- if(!Array.isArray(trace.pull)) return; // this can only happen with array pulls
-
- for(i = 0; i < wholeSide.length; i++) {
- otherPt = wholeSide[i];
-
- // overlap can only happen if the other point is pulled more than this one
- if(otherPt === thisPt || (
- (helpers.castOption(trace.pull, thisPt.pts) || 0) >=
- (helpers.castOption(trace.pull, otherPt.pts) || 0))
- ) {
- continue;
- }
-
- if((thisPt.pxmid[1] - otherPt.pxmid[1]) * yDiffSign > 0) {
- // closer to the equator - by construction all of these happen first
- // move the text vertically to get away from these slices
- otherOuterY = otherPt.cyFinal + farthestY(otherPt.px0[1], otherPt.px1[1]);
- newExtraY = otherOuterY - thisInnerY - thisPt.labelExtraY;
-
- if(newExtraY * yDiffSign > 0) thisPt.labelExtraY += newExtraY;
- } else if((thisOuterY + thisPt.labelExtraY - thisSliceOuterY) * yDiffSign > 0) {
- // farther from the equator - happens after we've done all the
- // vertical moving we're going to do
- // move horizontally to get away from these more polar slices
-
- // if we're moving horz. based on a slice that's several slices away from this one
- // then we need some extra space for the lines to labels between them
- xBuffer = 3 * xDiffSign * Math.abs(i - wholeSide.indexOf(thisPt));
-
- otherOuterX = otherPt.cxFinal + farthestX(otherPt.px0[0], otherPt.px1[0]);
- newExtraX = otherOuterX + xBuffer - (thisPt.cxFinal + thisPt.pxmid[0]) - thisPt.labelExtraX;
-
- if(newExtraX * xDiffSign > 0) thisPt.labelExtraX += newExtraX;
- }
- }
- }
-
- for(yHalf = 0; yHalf < 2; yHalf++) {
- equatorFirst = yHalf ? topFirst : bottomFirst;
- farthestY = yHalf ? Math.max : Math.min;
- yDiffSign = yHalf ? 1 : -1;
-
- for(xHalf = 0; xHalf < 2; xHalf++) {
- farthestX = xHalf ? Math.max : Math.min;
- xDiffSign = xHalf ? 1 : -1;
-
- // first sort the array
- // note this is a copy of cd, so cd itself doesn't get sorted
- // but we can still modify points in place.
- thisQuad = quadrants[yHalf][xHalf];
- thisQuad.sort(equatorFirst);
-
- oppositeQuad = quadrants[1 - yHalf][xHalf];
- wholeSide = oppositeQuad.concat(thisQuad);
-
- thisQuadOutside = [];
- for(i = 0; i < thisQuad.length; i++) {
- if(thisQuad[i].yLabelMid !== undefined) thisQuadOutside.push(thisQuad[i]);
- }
-
- firstOppositeOutsidePt = false;
- for(i = 0; yHalf && i < oppositeQuad.length; i++) {
- if(oppositeQuad[i].yLabelMid !== undefined) {
- firstOppositeOutsidePt = oppositeQuad[i];
- break;
- }
- }
-
- // each needs to avoid the previous
- for(i = 0; i < thisQuadOutside.length; i++) {
- var prevPt = i && thisQuadOutside[i - 1];
- // bottom half needs to avoid the first label of the top half
- // top half we still need to call scootOneLabel on the first slice
- // so we can avoid other slices, but we don't pass a prevPt
- if(firstOppositeOutsidePt && !i) prevPt = firstOppositeOutsidePt;
- scootOneLabel(thisQuadOutside[i], prevPt);
- }
- }
- }
-}
-
-function layoutAreas(cdModule, plotSize) {
- var scaleGroups = [];
-
- // figure out the center and maximum radius
- for(var i = 0; i < cdModule.length; i++) {
- var cd0 = cdModule[i][0];
- var trace = cd0.trace;
-
- var domain = trace.domain;
- var width = plotSize.w * (domain.x[1] - domain.x[0]);
- var height = plotSize.h * (domain.y[1] - domain.y[0]);
- // leave some space for the title, if it will be displayed outside
- if(trace.title.text && trace.title.position !== 'middle center') {
- height -= getTitleSpace(cd0, plotSize);
- }
-
- var rx = width / 2;
- var ry = height / 2;
- if(trace.type === 'funnelarea' && !trace.scalegroup) {
- ry /= trace.aspectratio;
- }
-
- cd0.r = Math.min(rx, ry) / (1 + getMaxPull(trace));
-
- cd0.cx = plotSize.l + plotSize.w * (trace.domain.x[1] + trace.domain.x[0]) / 2;
- cd0.cy = plotSize.t + plotSize.h * (1 - trace.domain.y[0]) - height / 2;
- if(trace.title.text && trace.title.position.indexOf('bottom') !== -1) {
- cd0.cy -= getTitleSpace(cd0, plotSize);
- }
-
- if(trace.scalegroup && scaleGroups.indexOf(trace.scalegroup) === -1) {
- scaleGroups.push(trace.scalegroup);
- }
- }
-
- groupScale(cdModule, scaleGroups);
-}
-
-function groupScale(cdModule, scaleGroups) {
- var cd0, i, trace;
-
- // scale those that are grouped
- for(var k = 0; k < scaleGroups.length; k++) {
- var min = Infinity;
- var g = scaleGroups[k];
-
- for(i = 0; i < cdModule.length; i++) {
- cd0 = cdModule[i][0];
- trace = cd0.trace;
-
- if(trace.scalegroup === g) {
- var area;
- if(trace.type === 'pie') {
- area = cd0.r * cd0.r;
- } else if(trace.type === 'funnelarea') {
- var rx, ry;
-
- if(trace.aspectratio > 1) {
- rx = cd0.r;
- ry = rx / trace.aspectratio;
- } else {
- ry = cd0.r;
- rx = ry * trace.aspectratio;
- }
-
- rx *= (1 + trace.baseratio) / 2;
-
- area = rx * ry;
- }
-
- min = Math.min(min, area / cd0.vTotal);
- }
- }
-
- for(i = 0; i < cdModule.length; i++) {
- cd0 = cdModule[i][0];
- trace = cd0.trace;
- if(trace.scalegroup === g) {
- var v = min * cd0.vTotal;
- if(trace.type === 'funnelarea') {
- v /= (1 + trace.baseratio) / 2;
- v /= trace.aspectratio;
- }
-
- cd0.r = Math.sqrt(v);
- }
- }
- }
-}
-
-function setCoords(cd) {
- var cd0 = cd[0];
- var trace = cd0.trace;
- var currentAngle = trace.rotation * Math.PI / 180;
- var angleFactor = 2 * Math.PI / cd0.vTotal;
- var firstPt = 'px0';
- var lastPt = 'px1';
-
- var i, cdi, currentCoords;
-
- if(trace.direction === 'counterclockwise') {
- for(i = 0; i < cd.length; i++) {
- if(!cd[i].hidden) break; // find the first non-hidden slice
- }
- if(i === cd.length) return; // all slices hidden
-
- currentAngle += angleFactor * cd[i].v;
- angleFactor *= -1;
- firstPt = 'px1';
- lastPt = 'px0';
- }
-
- function getCoords(angle) {
- return [cd0.r * Math.sin(angle), -cd0.r * Math.cos(angle)];
- }
-
- currentCoords = getCoords(currentAngle);
-
- for(i = 0; i < cd.length; i++) {
- cdi = cd[i];
- if(cdi.hidden) continue;
-
- cdi[firstPt] = currentCoords;
-
- currentAngle += angleFactor * cdi.v / 2;
- cdi.pxmid = getCoords(currentAngle);
- cdi.midangle = currentAngle;
-
- currentAngle += angleFactor * cdi.v / 2;
- currentCoords = getCoords(currentAngle);
-
- cdi[lastPt] = currentCoords;
-
- cdi.largeArc = (cdi.v > cd0.vTotal / 2) ? 1 : 0;
-
- cdi.halfangle = Math.PI * Math.min(cdi.v / cd0.vTotal, 0.5);
- cdi.ring = 1 - trace.hole;
- cdi.rInscribed = getInscribedRadiusFraction(cdi, cd0);
- }
-}
-
-module.exports = {
- plot: plot,
- transformInsideText: transformInsideText,
- determineInsideTextFont: determineInsideTextFont,
- positionTitleOutside: positionTitleOutside,
- prerenderTitles: prerenderTitles,
- layoutAreas: layoutAreas,
- attachFxHandlers: attachFxHandlers,
-};
-
-},{"../../components/color":51,"../../components/drawing":72,"../../components/fx":90,"../../lib":168,"../../lib/svg_text_utils":189,"./event_data":356,"./helpers":357,"d3":16}],362:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var d3 = _dereq_('d3');
-
-var styleOne = _dereq_('./style_one');
-
-module.exports = function style(gd) {
- gd._fullLayout._pielayer.selectAll('.trace').each(function(cd) {
- var cd0 = cd[0];
- var trace = cd0.trace;
- var traceSelection = d3.select(this);
-
- traceSelection.style({opacity: trace.opacity});
-
- traceSelection.selectAll('path.surface').each(function(pt) {
- d3.select(this).call(styleOne, pt, trace);
- });
- });
-};
-
-},{"./style_one":363,"d3":16}],363:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Color = _dereq_('../../components/color');
-var castOption = _dereq_('./helpers').castOption;
-
-module.exports = function styleOne(s, pt, trace) {
- var line = trace.marker.line;
- var lineColor = castOption(line.color, pt.pts) || Color.defaultLine;
- var lineWidth = castOption(line.width, pt.pts) || 0;
-
- s.style('stroke-width', lineWidth)
- .call(Color.fill, pt.color)
- .call(Color.stroke, lineColor);
-};
-
-},{"../../components/color":51,"./helpers":357}],364:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-
-// arrayOk attributes, merge them into calcdata array
-module.exports = function arraysToCalcdata(cd, trace) {
- // so each point knows which index it originally came from
- for(var i = 0; i < cd.length; i++) cd[i].i = i;
-
- Lib.mergeArray(trace.text, cd, 'tx');
- Lib.mergeArray(trace.hovertext, cd, 'htx');
- Lib.mergeArray(trace.customdata, cd, 'data');
- Lib.mergeArray(trace.textposition, cd, 'tp');
- if(trace.textfont) {
- Lib.mergeArray(trace.textfont.size, cd, 'ts');
- Lib.mergeArray(trace.textfont.color, cd, 'tc');
- Lib.mergeArray(trace.textfont.family, cd, 'tf');
- }
-
- var marker = trace.marker;
- if(marker) {
- Lib.mergeArray(marker.size, cd, 'ms');
- Lib.mergeArray(marker.opacity, cd, 'mo');
- Lib.mergeArray(marker.symbol, cd, 'mx');
- Lib.mergeArray(marker.color, cd, 'mc');
-
- var markerLine = marker.line;
- if(marker.line) {
- Lib.mergeArray(markerLine.color, cd, 'mlc');
- Lib.mergeArray(markerLine.width, cd, 'mlw');
- }
-
- var markerGradient = marker.gradient;
- if(markerGradient && markerGradient.type !== 'none') {
- Lib.mergeArray(markerGradient.type, cd, 'mgt');
- Lib.mergeArray(markerGradient.color, cd, 'mgc');
- }
- }
-};
-
-},{"../../lib":168}],365:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
-var colorScaleAttrs = _dereq_('../../components/colorscale/attributes');
-var fontAttrs = _dereq_('../../plots/font_attributes');
-var dash = _dereq_('../../components/drawing/attributes').dash;
-
-var Drawing = _dereq_('../../components/drawing');
-var constants = _dereq_('./constants');
-var extendFlat = _dereq_('../../lib/extend').extendFlat;
-
-module.exports = {
- x: {
- valType: 'data_array',
- editType: 'calc+clearAxisTypes',
- anim: true,
-
- },
- x0: {
- valType: 'any',
- dflt: 0,
-
- editType: 'calc+clearAxisTypes',
- anim: true,
-
- },
- dx: {
- valType: 'number',
- dflt: 1,
-
- editType: 'calc',
- anim: true,
-
- },
- y: {
- valType: 'data_array',
- editType: 'calc+clearAxisTypes',
- anim: true,
-
- },
- y0: {
- valType: 'any',
- dflt: 0,
-
- editType: 'calc+clearAxisTypes',
- anim: true,
-
- },
- dy: {
- valType: 'number',
- dflt: 1,
-
- editType: 'calc',
- anim: true,
-
- },
-
- stackgroup: {
- valType: 'string',
-
- dflt: '',
- editType: 'calc',
-
- },
- orientation: {
- valType: 'enumerated',
-
- values: ['v', 'h'],
- editType: 'calc',
-
- },
- groupnorm: {
- valType: 'enumerated',
- values: ['', 'fraction', 'percent'],
- dflt: '',
-
- editType: 'calc',
-
- },
- stackgaps: {
- valType: 'enumerated',
- values: ['infer zero', 'interpolate'],
- dflt: 'infer zero',
-
- editType: 'calc',
-
- },
-
- text: {
- valType: 'string',
-
- dflt: '',
- arrayOk: true,
- editType: 'calc',
-
- },
- hovertext: {
- valType: 'string',
-
- dflt: '',
- arrayOk: true,
- editType: 'style',
-
- },
- mode: {
- valType: 'flaglist',
- flags: ['lines', 'markers', 'text'],
- extras: ['none'],
-
- editType: 'calc',
-
- },
- hoveron: {
- valType: 'flaglist',
- flags: ['points', 'fills'],
-
- editType: 'style',
-
- },
- hovertemplate: hovertemplateAttrs({}, {
- keys: constants.eventDataKeys
- }),
- line: {
- color: {
- valType: 'color',
-
- editType: 'style',
- anim: true,
-
- },
- width: {
- valType: 'number',
- min: 0,
- dflt: 2,
-
- editType: 'style',
- anim: true,
-
- },
- shape: {
- valType: 'enumerated',
- values: ['linear', 'spline', 'hv', 'vh', 'hvh', 'vhv'],
- dflt: 'linear',
-
- editType: 'plot',
-
- },
- smoothing: {
- valType: 'number',
- min: 0,
- max: 1.3,
- dflt: 1,
-
- editType: 'plot',
-
- },
- dash: extendFlat({}, dash, {editType: 'style'}),
- simplify: {
- valType: 'boolean',
- dflt: true,
-
- editType: 'plot',
-
- },
- editType: 'plot'
- },
-
- connectgaps: {
- valType: 'boolean',
- dflt: false,
-
- editType: 'calc',
-
- },
- cliponaxis: {
- valType: 'boolean',
- dflt: true,
-
- editType: 'plot',
-
- },
-
- fill: {
- valType: 'enumerated',
- values: ['none', 'tozeroy', 'tozerox', 'tonexty', 'tonextx', 'toself', 'tonext'],
-
- editType: 'calc',
-
- },
- fillcolor: {
- valType: 'color',
-
- editType: 'style',
- anim: true,
-
- },
- marker: extendFlat({
- symbol: {
- valType: 'enumerated',
- values: Drawing.symbolList,
- dflt: 'circle',
- arrayOk: true,
-
- editType: 'style',
-
- },
- opacity: {
- valType: 'number',
- min: 0,
- max: 1,
- arrayOk: true,
-
- editType: 'style',
- anim: true,
-
- },
- size: {
- valType: 'number',
- min: 0,
- dflt: 6,
- arrayOk: true,
-
- editType: 'calc',
- anim: true,
-
- },
- maxdisplayed: {
- valType: 'number',
- min: 0,
- dflt: 0,
-
- editType: 'plot',
-
- },
- sizeref: {
- valType: 'number',
- dflt: 1,
-
- editType: 'calc',
-
- },
- sizemin: {
- valType: 'number',
- min: 0,
- dflt: 0,
-
- editType: 'calc',
-
- },
- sizemode: {
- valType: 'enumerated',
- values: ['diameter', 'area'],
- dflt: 'diameter',
-
- editType: 'calc',
-
- },
-
- line: extendFlat({
- width: {
- valType: 'number',
- min: 0,
- arrayOk: true,
-
- editType: 'style',
- anim: true,
-
- },
- editType: 'calc'
- },
- colorScaleAttrs('marker.line', {anim: true})
- ),
- gradient: {
- type: {
- valType: 'enumerated',
- values: ['radial', 'horizontal', 'vertical', 'none'],
- arrayOk: true,
- dflt: 'none',
-
- editType: 'calc',
-
- },
- color: {
- valType: 'color',
- arrayOk: true,
-
- editType: 'calc',
-
- },
- editType: 'calc'
- },
- editType: 'calc'
- },
- colorScaleAttrs('marker', {anim: true})
- ),
- selected: {
- marker: {
- opacity: {
- valType: 'number',
- min: 0,
- max: 1,
-
- editType: 'style',
-
- },
- color: {
- valType: 'color',
-
- editType: 'style',
-
- },
- size: {
- valType: 'number',
- min: 0,
-
- editType: 'style',
-
- },
- editType: 'style'
- },
- textfont: {
- color: {
- valType: 'color',
-
- editType: 'style',
-
- },
- editType: 'style'
- },
- editType: 'style'
- },
- unselected: {
- marker: {
- opacity: {
- valType: 'number',
- min: 0,
- max: 1,
-
- editType: 'style',
-
- },
- color: {
- valType: 'color',
-
- editType: 'style',
-
- },
- size: {
- valType: 'number',
- min: 0,
-
- editType: 'style',
-
- },
- editType: 'style'
- },
- textfont: {
- color: {
- valType: 'color',
-
- editType: 'style',
-
- },
- editType: 'style'
- },
- editType: 'style'
- },
-
- textposition: {
- valType: 'enumerated',
- values: [
- 'top left', 'top center', 'top right',
- 'middle left', 'middle center', 'middle right',
- 'bottom left', 'bottom center', 'bottom right'
- ],
- dflt: 'middle center',
- arrayOk: true,
-
- editType: 'calc',
-
- },
- textfont: fontAttrs({
- editType: 'calc',
- colorEditType: 'style',
- arrayOk: true,
-
- }),
-
- r: {
- valType: 'data_array',
- editType: 'calc',
-
- },
- t: {
- valType: 'data_array',
- editType: 'calc',
-
- }
-};
-
-},{"../../components/colorscale/attributes":58,"../../components/drawing":72,"../../components/drawing/attributes":71,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../../plots/font_attributes":238,"./constants":369}],366:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var isNumeric = _dereq_('fast-isnumeric');
-var Lib = _dereq_('../../lib');
-
-var Axes = _dereq_('../../plots/cartesian/axes');
-var BADNUM = _dereq_('../../constants/numerical').BADNUM;
-
-var subTypes = _dereq_('./subtypes');
-var calcColorscale = _dereq_('./colorscale_calc');
-var arraysToCalcdata = _dereq_('./arrays_to_calcdata');
-var calcSelection = _dereq_('./calc_selection');
-
-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 x = xa.makeCalcdata(trace, 'x');
- var y = ya.makeCalcdata(trace, 'y');
- var serieslen = trace._length;
- var cd = new Array(serieslen);
- var ids = trace.ids;
- var stackGroupOpts = getStackOpts(trace, fullLayout, xa, ya);
- var interpolateGaps = false;
- var isV, i, j, k, interpolate, vali;
-
- setFirstScatter(fullLayout, trace);
-
- var xAttr = 'x';
- var yAttr = 'y';
- var posAttr;
- if(stackGroupOpts) {
- Lib.pushUnique(stackGroupOpts.traceIndices, trace._expandedIndex);
- isV = stackGroupOpts.orientation === 'v';
-
- // size, like we use for bar
- if(isV) {
- yAttr = 's';
- posAttr = 'x';
- } else {
- xAttr = 's';
- posAttr = 'y';
- }
- interpolate = stackGroupOpts.stackgaps === 'interpolate';
- } else {
- var ppad = calcMarkerSize(trace, serieslen);
- calcAxisExpansion(gd, trace, xa, ya, x, y, ppad);
- }
-
- for(i = 0; i < serieslen; i++) {
- var cdi = cd[i] = {};
- var xValid = isNumeric(x[i]);
- var yValid = isNumeric(y[i]);
- if(xValid && yValid) {
- cdi[xAttr] = x[i];
- cdi[yAttr] = y[i];
- } else if(stackGroupOpts && (isV ? xValid : yValid)) {
- // if we're stacking we need to hold on to all valid positions
- // even with invalid sizes
-
- cdi[posAttr] = isV ? x[i] : y[i];
- cdi.gap = true;
- if(interpolate) {
- cdi.s = BADNUM;
- interpolateGaps = true;
- } else {
- cdi.s = 0;
- }
- } else {
- cdi[xAttr] = cdi[yAttr] = BADNUM;
- }
-
- if(ids) {
- cdi.id = String(ids[i]);
- }
- }
-
- arraysToCalcdata(cd, trace);
- calcColorscale(gd, trace);
- calcSelection(cd, trace);
-
- if(stackGroupOpts) {
- // remove bad positions and sort
- // note that original indices get added to cd in arraysToCalcdata
- i = 0;
- while(i < cd.length) {
- if(cd[i][posAttr] === BADNUM) {
- cd.splice(i, 1);
- } else i++;
- }
-
- Lib.sort(cd, function(a, b) {
- return (a[posAttr] - b[posAttr]) || (a.i - b.i);
- });
-
- if(interpolateGaps) {
- // first fill the beginning with constant from the first point
- i = 0;
- while(i < cd.length - 1 && cd[i].gap) {
- i++;
- }
- vali = cd[i].s;
- if(!vali) vali = cd[i].s = 0; // in case of no data AT ALL in this trace - use 0
- for(j = 0; j < i; j++) {
- cd[j].s = vali;
- }
- // then fill the end with constant from the last point
- k = cd.length - 1;
- while(k > i && cd[k].gap) {
- k--;
- }
- vali = cd[k].s;
- for(j = cd.length - 1; j > k; j--) {
- cd[j].s = vali;
- }
- // now interpolate internal gaps linearly
- while(i < k) {
- i++;
- if(cd[i].gap) {
- j = i + 1;
- while(cd[j].gap) {
- j++;
- }
- var pos0 = cd[i - 1][posAttr];
- var size0 = cd[i - 1].s;
- var m = (cd[j].s - size0) / (cd[j][posAttr] - pos0);
- while(i < j) {
- cd[i].s = size0 + (cd[i][posAttr] - pos0) * m;
- i++;
- }
- }
- }
- }
- }
-
- return cd;
-}
-
-function calcAxisExpansion(gd, trace, xa, ya, x, y, ppad) {
- var serieslen = trace._length;
- var fullLayout = gd._fullLayout;
- var xId = xa._id;
- var yId = ya._id;
- var firstScatter = fullLayout._firstScatter[firstScatterGroup(trace)] === trace.uid;
- var stackOrientation = (getStackOpts(trace, fullLayout, xa, ya) || {}).orientation;
- var fill = trace.fill;
-
- // cancel minimum tick spacings (only applies to bars and boxes)
- xa._minDtick = 0;
- ya._minDtick = 0;
-
- // check whether bounds should be tight, padded, extended to zero...
- // most cases both should be padded on both ends, so start with that.
- var xOptions = {padded: true};
- var yOptions = {padded: true};
-
- if(ppad) {
- xOptions.ppad = yOptions.ppad = ppad;
- }
-
- // TODO: text size
-
- var openEnded = serieslen < 2 || (x[0] !== x[serieslen - 1]) || (y[0] !== y[serieslen - 1]);
-
- if(openEnded && (
- (fill === 'tozerox') ||
- ((fill === 'tonextx') && (firstScatter || stackOrientation === 'h'))
- )) {
- // include zero (tight) and extremes (padded) if fill to zero
- // (unless the shape is closed, then it's just filling the shape regardless)
-
- xOptions.tozero = true;
- } else if(!(trace.error_y || {}).visible && (
- // if no error bars, markers or text, or fill to y=0 remove x padding
-
- (fill === 'tonexty' || fill === 'tozeroy') ||
- (!subTypes.hasMarkers(trace) && !subTypes.hasText(trace))
- )) {
- xOptions.padded = false;
- xOptions.ppad = 0;
- }
-
- if(openEnded && (
- (fill === 'tozeroy') ||
- ((fill === 'tonexty') && (firstScatter || stackOrientation === 'v'))
- )) {
- // now check for y - rather different logic, though still mostly padded both ends
- // include zero (tight) and extremes (padded) if fill to zero
- // (unless the shape is closed, then it's just filling the shape regardless)
-
- yOptions.tozero = true;
- } else if(fill === 'tonextx' || fill === 'tozerox') {
- // tight y: any x fill
-
- yOptions.padded = false;
- }
-
- // N.B. asymmetric splom traces call this with blank {} xa or ya
- if(xId) trace._extremes[xId] = Axes.findExtremes(xa, x, xOptions);
- if(yId) trace._extremes[yId] = Axes.findExtremes(ya, y, yOptions);
-}
-
-function calcMarkerSize(trace, serieslen) {
- if(!subTypes.hasMarkers(trace)) return;
-
- // Treat size like x or y arrays --- Run d2c
- // this needs to go before ppad computation
- var marker = trace.marker;
- var sizeref = 1.6 * (trace.marker.sizeref || 1);
- var markerTrans;
-
- if(trace.marker.sizemode === 'area') {
- markerTrans = function(v) {
- return Math.max(Math.sqrt((v || 0) / sizeref), 3);
- };
- } else {
- markerTrans = function(v) {
- return Math.max((v || 0) / sizeref, 3);
- };
- }
-
- if(Lib.isArrayOrTypedArray(marker.size)) {
- // I tried auto-type but category and dates dont make much sense.
- var ax = {type: 'linear'};
- Axes.setConvert(ax);
-
- var s = ax.makeCalcdata(trace.marker, 'size');
-
- var sizeOut = new Array(serieslen);
- for(var i = 0; i < serieslen; i++) {
- sizeOut[i] = markerTrans(s[i]);
- }
- return sizeOut;
- } else {
- return markerTrans(marker.size);
- }
-}
-
-/**
- * mark the first scatter trace for each subplot
- * note that scatter and scattergl each get their own first trace
- * note also that I'm doing this during calc rather than supplyDefaults
- * so I don't need to worry about transforms, but if we ever do
- * per-trace calc this will get confused.
- */
-function setFirstScatter(fullLayout, trace) {
- var group = firstScatterGroup(trace);
- var firstScatter = fullLayout._firstScatter;
- if(!firstScatter[group]) firstScatter[group] = trace.uid;
-}
-
-function firstScatterGroup(trace) {
- var stackGroup = trace.stackgroup;
- return trace.xaxis + trace.yaxis + trace.type +
- (stackGroup ? '-' + stackGroup : '');
-}
-
-function getStackOpts(trace, fullLayout, xa, ya) {
- var stackGroup = trace.stackgroup;
- if(!stackGroup) return;
- var stackOpts = fullLayout._scatterStackOpts[xa._id + ya._id][stackGroup];
- var stackAx = stackOpts.orientation === 'v' ? ya : xa;
- // Allow stacking only on numeric axes
- // calc is a little late to be figuring this out, but during supplyDefaults
- // we don't know the axis type yet
- if(stackAx.type === 'linear' || stackAx.type === 'log') return stackOpts;
-}
-
-module.exports = {
- calc: calc,
- calcMarkerSize: calcMarkerSize,
- calcAxisExpansion: calcAxisExpansion,
- setFirstScatter: setFirstScatter,
- getStackOpts: getStackOpts
-};
-
-},{"../../constants/numerical":149,"../../lib":168,"../../plots/cartesian/axes":212,"./arrays_to_calcdata":364,"./calc_selection":367,"./colorscale_calc":368,"./subtypes":388,"fast-isnumeric":18}],367:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-module.exports = function calcSelection(cd, trace) {
- if(Lib.isArrayOrTypedArray(trace.selectedpoints)) {
- Lib.tagSelected(cd, trace);
- }
-};
-
-},{"../../lib":168}],368:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var hasColorscale = _dereq_('../../components/colorscale/helpers').hasColorscale;
-var calcColorscale = _dereq_('../../components/colorscale/calc');
-
-var subTypes = _dereq_('./subtypes');
-
-module.exports = function calcMarkerColorscale(gd, trace) {
- if(subTypes.hasLines(trace) && hasColorscale(trace, 'line')) {
- calcColorscale(gd, trace, {
- vals: trace.line.color,
- containerStr: 'line',
- cLetter: 'c'
- });
- }
-
- if(subTypes.hasMarkers(trace)) {
- if(hasColorscale(trace, 'marker')) {
- calcColorscale(gd, trace, {
- vals: trace.marker.color,
- containerStr: 'marker',
- cLetter: 'c'
- });
- }
- if(hasColorscale(trace, 'marker.line')) {
- calcColorscale(gd, trace, {
- vals: trace.marker.line.color,
- containerStr: 'marker.line',
- cLetter: 'c'
- });
- }
- }
-};
-
-},{"../../components/colorscale/calc":59,"../../components/colorscale/helpers":62,"./subtypes":388}],369:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-module.exports = {
- PTS_LINESONLY: 20,
-
- // fixed parameters of clustering and clipping algorithms
-
- // fraction of clustering tolerance "so close we don't even consider it a new point"
- minTolerance: 0.2,
- // how fast does clustering tolerance increase as you get away from the visible region
- toleranceGrowth: 10,
-
- // number of viewport sizes away from the visible region
- // at which we clip all lines to the perimeter
- maxScreensAway: 20,
-
- eventDataKeys: []
-};
-
-},{}],370:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var calc = _dereq_('./calc');
-
-/*
- * Scatter stacking & normalization calculations
- * runs per subplot, and can handle multiple stacking groups
- */
-
-module.exports = function crossTraceCalc(gd, plotinfo) {
- var xa = plotinfo.xaxis;
- var ya = plotinfo.yaxis;
- var subplot = xa._id + ya._id;
-
- var subplotStackOpts = gd._fullLayout._scatterStackOpts[subplot];
- if(!subplotStackOpts) return;
-
- var calcTraces = gd.calcdata;
-
- var i, j, k, i2, cd, cd0, posj, sumj, norm;
- var groupOpts, interpolate, groupnorm, posAttr, valAttr;
- var hasAnyBlanks;
-
- for(var stackGroup in subplotStackOpts) {
- groupOpts = subplotStackOpts[stackGroup];
- var indices = groupOpts.traceIndices;
-
- // can get here with no indices if the stack axis is non-numeric
- if(!indices.length) continue;
-
- interpolate = groupOpts.stackgaps === 'interpolate';
- groupnorm = groupOpts.groupnorm;
- if(groupOpts.orientation === 'v') {
- posAttr = 'x';
- valAttr = 'y';
- } else {
- posAttr = 'y';
- valAttr = 'x';
- }
- hasAnyBlanks = new Array(indices.length);
- for(i = 0; i < hasAnyBlanks.length; i++) {
- hasAnyBlanks[i] = false;
- }
-
- // Collect the complete set of all positions across ALL traces.
- // Start with the first trace, then interleave items from later traces
- // as needed.
- // Fill in mising items as we go.
- cd0 = calcTraces[indices[0]];
- var allPositions = new Array(cd0.length);
- for(i = 0; i < cd0.length; i++) {
- allPositions[i] = cd0[i][posAttr];
- }
-
- for(i = 1; i < indices.length; i++) {
- cd = calcTraces[indices[i]];
-
- for(j = k = 0; j < cd.length; j++) {
- posj = cd[j][posAttr];
- for(; posj > allPositions[k] && k < allPositions.length; k++) {
- // the current trace is missing a position from some previous trace(s)
- insertBlank(cd, j, allPositions[k], i, hasAnyBlanks, interpolate, posAttr);
- j++;
- }
- if(posj !== allPositions[k]) {
- // previous trace(s) are missing a position from the current trace
- for(i2 = 0; i2 < i; i2++) {
- insertBlank(calcTraces[indices[i2]], k, posj, i2, hasAnyBlanks, interpolate, posAttr);
- }
- allPositions.splice(k, 0, posj);
- }
- k++;
- }
- for(; k < allPositions.length; k++) {
- insertBlank(cd, j, allPositions[k], i, hasAnyBlanks, interpolate, posAttr);
- j++;
- }
- }
-
- var serieslen = allPositions.length;
-
- // stack (and normalize)!
- for(j = 0; j < cd0.length; j++) {
- sumj = cd0[j][valAttr] = cd0[j].s;
- for(i = 1; i < indices.length; i++) {
- cd = calcTraces[indices[i]];
- cd[0].trace._rawLength = cd[0].trace._length;
- cd[0].trace._length = serieslen;
- sumj += cd[j].s;
- cd[j][valAttr] = sumj;
- }
-
- if(groupnorm) {
- norm = ((groupnorm === 'fraction') ? sumj : (sumj / 100)) || 1;
- for(i = 0; i < indices.length; i++) {
- var cdj = calcTraces[indices[i]][j];
- cdj[valAttr] /= norm;
- cdj.sNorm = cdj.s / norm;
- }
- }
- }
-
- // autorange
- for(i = 0; i < indices.length; i++) {
- cd = calcTraces[indices[i]];
- var trace = cd[0].trace;
- var ppad = calc.calcMarkerSize(trace, trace._rawLength);
- var arrayPad = Array.isArray(ppad);
- if((ppad && hasAnyBlanks[i]) || arrayPad) {
- var ppadRaw = ppad;
- ppad = new Array(serieslen);
- for(j = 0; j < serieslen; j++) {
- ppad[j] = cd[j].gap ? 0 : (arrayPad ? ppadRaw[cd[j].i] : ppadRaw);
- }
- }
- var x = new Array(serieslen);
- var y = new Array(serieslen);
- for(j = 0; j < serieslen; j++) {
- x[j] = cd[j].x;
- y[j] = cd[j].y;
- }
- calc.calcAxisExpansion(gd, trace, xa, ya, x, y, ppad);
-
- // while we're here (in a loop over all traces in the stack)
- // record the orientation, so hover can find it easily
- cd[0].t.orientation = groupOpts.orientation;
- }
- }
-};
-
-function insertBlank(calcTrace, index, position, traceIndex, hasAnyBlanks, interpolate, posAttr) {
- hasAnyBlanks[traceIndex] = true;
- var newEntry = {
- i: null,
- gap: true,
- s: 0
- };
- newEntry[posAttr] = position;
- calcTrace.splice(index, 0, newEntry);
- // Even if we're not interpolating, if one trace has multiple
- // values at the same position and this trace only has one value there,
- // we just duplicate that one value rather than insert a zero.
- // We also make it look like a real point - because it's ambiguous which
- // one really is the real one!
- if(index && position === calcTrace[index - 1][posAttr]) {
- var prevEntry = calcTrace[index - 1];
- newEntry.s = prevEntry.s;
- // TODO is it going to cause any problems to have multiple
- // calcdata points with the same index?
- newEntry.i = prevEntry.i;
- newEntry.gap = prevEntry.gap;
- } else if(interpolate) {
- newEntry.s = getInterp(calcTrace, index, position, posAttr);
- }
- if(!index) {
- // t and trace need to stay on the first cd entry
- calcTrace[0].t = calcTrace[1].t;
- calcTrace[0].trace = calcTrace[1].trace;
- delete calcTrace[1].t;
- delete calcTrace[1].trace;
- }
-}
-
-function getInterp(calcTrace, index, position, posAttr) {
- var pt0 = calcTrace[index - 1];
- var pt1 = calcTrace[index + 1];
- if(!pt1) return pt0.s;
- if(!pt0) return pt1.s;
- return pt0.s + (pt1.s - pt0.s) * (position - pt0[posAttr]) / (pt1[posAttr] - pt0[posAttr]);
-}
-
-},{"./calc":366}],371:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-
-// remove opacity for any trace that has a fill or is filled to
-module.exports = function crossTraceDefaults(fullData) {
- for(var i = 0; i < fullData.length; i++) {
- var tracei = fullData[i];
- if(tracei.type !== 'scatter') continue;
-
- var filli = tracei.fill;
- if(filli === 'none' || filli === 'toself') continue;
-
- tracei.opacity = undefined;
-
- if(filli === 'tonexty' || filli === 'tonextx') {
- for(var j = i - 1; j >= 0; j--) {
- var tracej = fullData[j];
-
- if((tracej.type === 'scatter') &&
- (tracej.xaxis === tracei.xaxis) &&
- (tracej.yaxis === tracei.yaxis)) {
- tracej.opacity = undefined;
- break;
- }
- }
- }
- }
-};
-
-},{}],372:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var Registry = _dereq_('../../registry');
-
-var attributes = _dereq_('./attributes');
-var constants = _dereq_('./constants');
-var subTypes = _dereq_('./subtypes');
-var handleXYDefaults = _dereq_('./xy_defaults');
-var handleStackDefaults = _dereq_('./stack_defaults');
-var handleMarkerDefaults = _dereq_('./marker_defaults');
-var handleLineDefaults = _dereq_('./line_defaults');
-var handleLineShapeDefaults = _dereq_('./line_shape_defaults');
-var handleTextDefaults = _dereq_('./text_defaults');
-var handleFillColorDefaults = _dereq_('./fillcolor_defaults');
-
-module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
- function coerce(attr, dflt) {
- return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
- }
-
- var len = handleXYDefaults(traceIn, traceOut, layout, coerce);
- if(!len) traceOut.visible = false;
-
- if(!traceOut.visible) return;
-
- var stackGroupOpts = handleStackDefaults(traceIn, traceOut, layout, coerce);
-
- var defaultMode = !stackGroupOpts && (len < constants.PTS_LINESONLY) ?
- 'lines+markers' : 'lines';
- coerce('text');
- coerce('hovertext');
- coerce('mode', defaultMode);
-
- if(subTypes.hasLines(traceOut)) {
- handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
- handleLineShapeDefaults(traceIn, traceOut, coerce);
- coerce('connectgaps');
- coerce('line.simplify');
- }
-
- if(subTypes.hasMarkers(traceOut)) {
- handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true});
- }
-
- if(subTypes.hasText(traceOut)) {
- handleTextDefaults(traceIn, traceOut, layout, coerce);
- }
-
- var dfltHoverOn = [];
-
- if(subTypes.hasMarkers(traceOut) || subTypes.hasText(traceOut)) {
- coerce('cliponaxis');
- coerce('marker.maxdisplayed');
- dfltHoverOn.push('points');
- }
-
- // It's possible for this default to be changed by a later trace.
- // We handle that case in some hacky code inside handleStackDefaults.
- coerce('fill', stackGroupOpts ? stackGroupOpts.fillDflt : 'none');
- if(traceOut.fill !== 'none') {
- handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce);
- if(!subTypes.hasLines(traceOut)) handleLineShapeDefaults(traceIn, traceOut, coerce);
- }
-
- var lineColor = (traceOut.line || {}).color;
- var markerColor = (traceOut.marker || {}).color;
-
- if(traceOut.fill === 'tonext' || traceOut.fill === 'toself') {
- dfltHoverOn.push('fills');
- }
- coerce('hoveron', dfltHoverOn.join('+') || 'points');
- if(traceOut.hoveron !== 'fills') coerce('hovertemplate');
- var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults');
- errorBarsSupplyDefaults(traceIn, traceOut, lineColor || markerColor || defaultColor, {axis: 'y'});
- errorBarsSupplyDefaults(traceIn, traceOut, lineColor || markerColor || defaultColor, {axis: 'x', inherit: 'y'});
-
- Lib.coerceSelectionMarkerOpacity(traceOut, coerce);
-};
-
-},{"../../lib":168,"../../registry":256,"./attributes":365,"./constants":369,"./fillcolor_defaults":373,"./line_defaults":377,"./line_shape_defaults":379,"./marker_defaults":383,"./stack_defaults":386,"./subtypes":388,"./text_defaults":389,"./xy_defaults":390}],373:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var Color = _dereq_('../../components/color');
-var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray;
-
-module.exports = function fillColorDefaults(traceIn, traceOut, defaultColor, coerce) {
- var inheritColorFromMarker = false;
-
- if(traceOut.marker) {
- // don't try to inherit a color array
- var markerColor = traceOut.marker.color;
- var markerLineColor = (traceOut.marker.line || {}).color;
-
- if(markerColor && !isArrayOrTypedArray(markerColor)) {
- inheritColorFromMarker = markerColor;
- } else if(markerLineColor && !isArrayOrTypedArray(markerLineColor)) {
- inheritColorFromMarker = markerLineColor;
- }
- }
-
- coerce('fillcolor', Color.addOpacity(
- (traceOut.line || {}).color ||
- inheritColorFromMarker ||
- defaultColor, 0.5
- ));
-};
-
-},{"../../components/color":51,"../../lib":168}],374:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var Color = _dereq_('../../components/color');
-var subtypes = _dereq_('./subtypes');
-
-
-module.exports = function getTraceColor(trace, di) {
- var lc, tc;
-
- // TODO: text modes
-
- if(trace.mode === 'lines') {
- lc = trace.line.color;
- return (lc && Color.opacity(lc)) ?
- lc : trace.fillcolor;
- } else if(trace.mode === 'none') {
- return trace.fill ? trace.fillcolor : '';
- } else {
- var mc = di.mcc || (trace.marker || {}).color;
- var mlc = di.mlcc || ((trace.marker || {}).line || {}).color;
-
- tc = (mc && Color.opacity(mc)) ? mc :
- (mlc && Color.opacity(mlc) &&
- (di.mlw || ((trace.marker || {}).line || {}).width)) ? mlc : '';
-
- if(tc) {
- // make sure the points aren't TOO transparent
- if(Color.opacity(tc) < 0.3) {
- return Color.addOpacity(tc, 0.3);
- } else return tc;
- } else {
- lc = (trace.line || {}).color;
- return (lc && Color.opacity(lc) &&
- subtypes.hasLines(trace) && trace.line.width) ?
- lc : trace.fillcolor;
- }
- }
-};
-
-},{"../../components/color":51,"./subtypes":388}],375:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var Fx = _dereq_('../../components/fx');
-var Registry = _dereq_('../../registry');
-var getTraceColor = _dereq_('./get_trace_color');
-var Color = _dereq_('../../components/color');
-var fillText = Lib.fillText;
-
-module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
- var cd = pointData.cd;
- var trace = cd[0].trace;
- var xa = pointData.xa;
- var ya = pointData.ya;
- var xpx = xa.c2p(xval);
- var ypx = ya.c2p(yval);
- var pt = [xpx, ypx];
- var hoveron = trace.hoveron || '';
- var minRad = (trace.mode.indexOf('markers') !== -1) ? 3 : 0.5;
-
- // look for points to hover on first, then take fills only if we
- // didn't find a point
- if(hoveron.indexOf('points') !== -1) {
- var dx = function(di) {
- // dx and dy are used in compare modes - here we want to always
- // prioritize the closest data point, at least as long as markers are
- // the same size or nonexistent, but still try to prioritize small markers too.
- var rad = Math.max(3, di.mrc || 0);
- var kink = 1 - 1 / rad;
- var dxRaw = Math.abs(xa.c2p(di.x) - xpx);
- var d = (dxRaw < rad) ? (kink * dxRaw / rad) : (dxRaw - rad + kink);
- return d;
- };
- var dy = function(di) {
- var rad = Math.max(3, di.mrc || 0);
- var kink = 1 - 1 / rad;
- var dyRaw = Math.abs(ya.c2p(di.y) - ypx);
- return (dyRaw < rad) ? (kink * dyRaw / rad) : (dyRaw - rad + kink);
- };
- var dxy = function(di) {
- // scatter points: d.mrc is the calculated marker radius
- // adjust the distance so if you're inside the marker it
- // always will show up regardless of point size, but
- // prioritize smaller points
- var rad = Math.max(minRad, di.mrc || 0);
- var dx = xa.c2p(di.x) - xpx;
- var dy = ya.c2p(di.y) - ypx;
- return Math.max(Math.sqrt(dx * dx + dy * dy) - rad, 1 - minRad / rad);
- };
- 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
- if(pointData.index !== false) {
- // the closest data point
- var di = cd[pointData.index];
- var xc = xa.c2p(di.x, true);
- var yc = ya.c2p(di.y, true);
- var rad = di.mrc || 1;
-
- // now we're done using the whole `calcdata` array, replace the
- // index with the original index (in case of inserted point from
- // stacked area)
- pointData.index = di.i;
-
- var orientation = cd[0].t.orientation;
- // TODO: for scatter and bar, option to show (sub)totals and
- // raw data? Currently stacked and/or normalized bars just show
- // the normalized individual sizes, so that's what I'm doing here
- // for now.
- var sizeVal = orientation && (di.sNorm || di.s);
- var xLabelVal = (orientation === 'h') ? sizeVal : di.x;
- var yLabelVal = (orientation === 'v') ? sizeVal : di.y;
-
- Lib.extendFlat(pointData, {
- color: getTraceColor(trace, di),
-
- x0: xc - rad,
- x1: xc + rad,
- xLabelVal: xLabelVal,
-
- y0: yc - rad,
- y1: yc + rad,
- yLabelVal: yLabelVal,
-
- spikeDistance: dxy(di),
- hovertemplate: trace.hovertemplate
- });
-
- fillText(di, trace, pointData);
- Registry.getComponentMethod('errorbars', 'hoverInfo')(di, trace, pointData);
-
- return [pointData];
- }
- }
-
- // even if hoveron is 'fills', only use it if we have polygons too
- if(hoveron.indexOf('fills') !== -1 && trace._polygons) {
- var polygons = trace._polygons;
- var polygonsIn = [];
- var inside = false;
- var xmin = Infinity;
- var xmax = -Infinity;
- var ymin = Infinity;
- var ymax = -Infinity;
-
- var i, j, polygon, pts, xCross, x0, x1, y0, y1;
-
- for(i = 0; i < polygons.length; i++) {
- polygon = polygons[i];
- // TODO: this is not going to work right for curved edges, it will
- // act as though they're straight. That's probably going to need
- // the elements themselves to capture the events. Worth it?
- if(polygon.contains(pt)) {
- inside = !inside;
- // TODO: need better than just the overall bounding box
- polygonsIn.push(polygon);
- ymin = Math.min(ymin, polygon.ymin);
- ymax = Math.max(ymax, polygon.ymax);
- }
- }
-
- if(inside) {
- // constrain ymin/max to the visible plot, so the label goes
- // at the middle of the piece you can see
- ymin = Math.max(ymin, 0);
- ymax = Math.min(ymax, ya._length);
-
- // find the overall left-most and right-most points of the
- // polygon(s) we're inside at their combined vertical midpoint.
- // This is where we will draw the hover label.
- // Note that this might not be the vertical midpoint of the
- // whole trace, if it's disjoint.
- var yAvg = (ymin + ymax) / 2;
- for(i = 0; i < polygonsIn.length; i++) {
- pts = polygonsIn[i].pts;
- for(j = 1; j < pts.length; j++) {
- y0 = pts[j - 1][1];
- y1 = pts[j][1];
- if((y0 > yAvg) !== (y1 >= yAvg)) {
- x0 = pts[j - 1][0];
- x1 = pts[j][0];
- if(y1 - y0) {
- xCross = x0 + (x1 - x0) * (yAvg - y0) / (y1 - y0);
- xmin = Math.min(xmin, xCross);
- xmax = Math.max(xmax, xCross);
- }
- }
- }
- }
-
- // constrain xmin/max to the visible plot now too
- xmin = Math.max(xmin, 0);
- xmax = Math.min(xmax, xa._length);
-
- // get only fill or line color for the hover color
- var color = Color.defaultLine;
- if(Color.opacity(trace.fillcolor)) color = trace.fillcolor;
- else if(Color.opacity((trace.line || {}).color)) {
- color = trace.line.color;
- }
-
- Lib.extendFlat(pointData, {
- // never let a 2D override 1D type as closest point
- // also: no spikeDistance, it's not allowed for fills
- distance: pointData.maxHoverDistance,
- x0: xmin,
- x1: xmax,
- y0: yAvg,
- y1: yAvg,
- color: color,
- hovertemplate: false
- });
-
- delete pointData.index;
-
- if(trace.text && !Array.isArray(trace.text)) {
- pointData.text = String(trace.text);
- } else pointData.text = trace.name;
-
- return [pointData];
- }
- }
-};
-
-},{"../../components/color":51,"../../components/fx":90,"../../lib":168,"../../registry":256,"./get_trace_color":374}],376:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var subtypes = _dereq_('./subtypes');
-
-module.exports = {
- hasLines: subtypes.hasLines,
- hasMarkers: subtypes.hasMarkers,
- hasText: subtypes.hasText,
- isBubble: subtypes.isBubble,
-
- attributes: _dereq_('./attributes'),
- supplyDefaults: _dereq_('./defaults'),
- crossTraceDefaults: _dereq_('./cross_trace_defaults'),
- calc: _dereq_('./calc').calc,
- crossTraceCalc: _dereq_('./cross_trace_calc'),
- arraysToCalcdata: _dereq_('./arrays_to_calcdata'),
- plot: _dereq_('./plot'),
- colorbar: _dereq_('./marker_colorbar'),
- style: _dereq_('./style').style,
- styleOnSelect: _dereq_('./style').styleOnSelect,
- hoverPoints: _dereq_('./hover'),
- selectPoints: _dereq_('./select'),
- animatable: true,
-
- moduleType: 'trace',
- name: 'scatter',
- basePlotModule: _dereq_('../../plots/cartesian'),
- categories: [
- 'cartesian', 'svg', 'symbols', 'errorBarsOK', 'showLegend', 'scatter-like',
- 'zoomScale'
- ],
- meta: {
-
- }
-};
-
-},{"../../plots/cartesian":223,"./arrays_to_calcdata":364,"./attributes":365,"./calc":366,"./cross_trace_calc":370,"./cross_trace_defaults":371,"./defaults":372,"./hover":375,"./marker_colorbar":382,"./plot":384,"./select":385,"./style":387,"./subtypes":388}],377:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray;
-var hasColorscale = _dereq_('../../components/colorscale/helpers').hasColorscale;
-var colorscaleDefaults = _dereq_('../../components/colorscale/defaults');
-
-module.exports = function lineDefaults(traceIn, traceOut, defaultColor, layout, coerce, opts) {
- var markerColor = (traceIn.marker || {}).color;
-
- coerce('line.color', defaultColor);
-
- if(hasColorscale(traceIn, 'line')) {
- colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'line.', cLetter: 'c'});
- } else {
- var lineColorDflt = (isArrayOrTypedArray(markerColor) ? false : markerColor) || defaultColor;
- coerce('line.color', lineColorDflt);
- }
-
- coerce('line.width');
- if(!(opts || {}).noDash) coerce('line.dash');
-};
-
-},{"../../components/colorscale/defaults":61,"../../components/colorscale/helpers":62,"../../lib":168}],378:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var numConstants = _dereq_('../../constants/numerical');
-var BADNUM = numConstants.BADNUM;
-var LOG_CLIP = numConstants.LOG_CLIP;
-var LOG_CLIP_PLUS = LOG_CLIP + 0.5;
-var LOG_CLIP_MINUS = LOG_CLIP - 0.5;
-var Lib = _dereq_('../../lib');
-var segmentsIntersect = Lib.segmentsIntersect;
-var constrain = Lib.constrain;
-var constants = _dereq_('./constants');
-
-
-module.exports = function linePoints(d, opts) {
- var xa = opts.xaxis;
- var ya = opts.yaxis;
- var xLog = xa.type === 'log';
- var yLog = ya.type === 'log';
- var xLen = xa._length;
- var yLen = ya._length;
- var connectGaps = opts.connectGaps;
- var baseTolerance = opts.baseTolerance;
- var shape = opts.shape;
- var linear = shape === 'linear';
- var fill = opts.fill && opts.fill !== 'none';
- var segments = [];
- var minTolerance = constants.minTolerance;
- var len = d.length;
- var pts = new Array(len);
- var pti = 0;
-
- var i;
-
- // pt variables are pixel coordinates [x,y] of one point
- // these four are the outputs of clustering on a line
- var clusterStartPt, clusterEndPt, clusterHighPt, clusterLowPt;
-
- // "this" is the next point we're considering adding to the cluster
- var thisPt;
-
- // did we encounter the high point first, then a low point, or vice versa?
- var clusterHighFirst;
-
- // the first two points in the cluster determine its unit vector
- // so the second is always in the "High" direction
- var clusterUnitVector;
-
- // the pixel delta from clusterStartPt
- var thisVector;
-
- // val variables are (signed) pixel distances along the cluster vector
- var clusterRefDist, clusterHighVal, clusterLowVal, thisVal;
-
- // deviation variables are (signed) pixel distances normal to the cluster vector
- var clusterMinDeviation, clusterMaxDeviation, thisDeviation;
-
- // turn one calcdata point into pixel coordinates
- function getPt(index) {
- var di = d[index];
- if(!di) return false;
- var x = xa.c2p(di.x);
- var y = ya.c2p(di.y);
-
- // if non-positive log values, set them VERY far off-screen
- // so the line looks essentially straight from the previous point.
- if(x === BADNUM) {
- if(xLog) x = xa.c2p(di.x, true);
- if(x === BADNUM) return false;
- // If BOTH were bad log values, make the line follow a constant
- // exponent rather than a constant slope
- if(yLog && y === BADNUM) {
- x *= Math.abs(xa._m * yLen * (xa._m > 0 ? LOG_CLIP_PLUS : LOG_CLIP_MINUS) /
- (ya._m * xLen * (ya._m > 0 ? LOG_CLIP_PLUS : LOG_CLIP_MINUS)));
- }
- x *= 1000;
- }
- if(y === BADNUM) {
- if(yLog) y = ya.c2p(di.y, true);
- if(y === BADNUM) return false;
- y *= 1000;
- }
- return [x, y];
- }
-
- function crossesViewport(xFrac0, yFrac0, xFrac1, yFrac1) {
- var dx = xFrac1 - xFrac0;
- var dy = yFrac1 - yFrac0;
- var dx0 = 0.5 - xFrac0;
- var dy0 = 0.5 - yFrac0;
- var norm2 = dx * dx + dy * dy;
- var dot = dx * dx0 + dy * dy0;
- if(dot > 0 && dot < norm2) {
- var cross = dx0 * dy - dy0 * dx;
- if(cross * cross < norm2) return true;
- }
- }
-
- var latestXFrac, latestYFrac;
- // if we're off-screen, increase tolerance over baseTolerance
- function getTolerance(pt, nextPt) {
- var xFrac = pt[0] / xLen;
- var yFrac = pt[1] / yLen;
- var offScreenFraction = Math.max(0, -xFrac, xFrac - 1, -yFrac, yFrac - 1);
- if(offScreenFraction && (latestXFrac !== undefined) &&
- crossesViewport(xFrac, yFrac, latestXFrac, latestYFrac)
- ) {
- offScreenFraction = 0;
- }
- if(offScreenFraction && nextPt &&
- crossesViewport(xFrac, yFrac, nextPt[0] / xLen, nextPt[1] / yLen)
- ) {
- offScreenFraction = 0;
- }
-
- return (1 + constants.toleranceGrowth * offScreenFraction) * baseTolerance;
- }
-
- function ptDist(pt1, pt2) {
- var dx = pt1[0] - pt2[0];
- var dy = pt1[1] - pt2[1];
- return Math.sqrt(dx * dx + dy * dy);
- }
-
- // last bit of filtering: clip paths that are VERY far off-screen
- // so we don't get near the browser's hard limit (+/- 2^29 px in Chrome and FF)
-
- var maxScreensAway = constants.maxScreensAway;
-
- // find the intersections between the segment from pt1 to pt2
- // and the large rectangle maxScreensAway around the viewport
- // if one of pt1 and pt2 is inside and the other outside, there
- // will be only one intersection.
- // if both are outside there will be 0 or 2 intersections
- // (or 1 if it's right at a corner - we'll treat that like 0)
- // returns an array of intersection pts
- var xEdge0 = -xLen * maxScreensAway;
- var xEdge1 = xLen * (1 + maxScreensAway);
- var yEdge0 = -yLen * maxScreensAway;
- var yEdge1 = yLen * (1 + maxScreensAway);
- var edges = [
- [xEdge0, yEdge0, xEdge1, yEdge0],
- [xEdge1, yEdge0, xEdge1, yEdge1],
- [xEdge1, yEdge1, xEdge0, yEdge1],
- [xEdge0, yEdge1, xEdge0, yEdge0]
- ];
- var xEdge, yEdge, lastXEdge, lastYEdge, lastFarPt, edgePt;
-
- // for linear line shape, edge intersections should be linearly interpolated
- // spline uses this too, which isn't precisely correct but is actually pretty
- // good, because Catmull-Rom weights far-away points less in creating the curvature
- function getLinearEdgeIntersections(pt1, pt2) {
- var out = [];
- var ptCount = 0;
- for(var i = 0; i < 4; i++) {
- var edge = edges[i];
- var ptInt = segmentsIntersect(
- pt1[0], pt1[1], pt2[0], pt2[1],
- edge[0], edge[1], edge[2], edge[3]
- );
- if(ptInt && (!ptCount ||
- Math.abs(ptInt.x - out[0][0]) > 1 ||
- Math.abs(ptInt.y - out[0][1]) > 1
- )) {
- ptInt = [ptInt.x, ptInt.y];
- // if we have 2 intersections, make sure the closest one to pt1 comes first
- if(ptCount && ptDist(ptInt, pt1) < ptDist(out[0], pt1)) out.unshift(ptInt);
- else out.push(ptInt);
- ptCount++;
- }
- }
- return out;
- }
-
- function onlyConstrainedPoint(pt) {
- if(pt[0] < xEdge0 || pt[0] > xEdge1 || pt[1] < yEdge0 || pt[1] > yEdge1) {
- return [constrain(pt[0], xEdge0, xEdge1), constrain(pt[1], yEdge0, yEdge1)];
- }
- }
-
- function sameEdge(pt1, pt2) {
- if(pt1[0] === pt2[0] && (pt1[0] === xEdge0 || pt1[0] === xEdge1)) return true;
- if(pt1[1] === pt2[1] && (pt1[1] === yEdge0 || pt1[1] === yEdge1)) return true;
- }
-
- // for line shapes hv and vh, movement in the two dimensions is decoupled,
- // so all we need to do is constrain each dimension independently
- function getHVEdgeIntersections(pt1, pt2) {
- var out = [];
- var ptInt1 = onlyConstrainedPoint(pt1);
- var ptInt2 = onlyConstrainedPoint(pt2);
- if(ptInt1 && ptInt2 && sameEdge(ptInt1, ptInt2)) return out;
-
- if(ptInt1) out.push(ptInt1);
- if(ptInt2) out.push(ptInt2);
- return out;
- }
-
- // hvh and vhv we sometimes have to move one of the intersection points
- // out BEYOND the clipping rect, by a maximum of a factor of 2, so that
- // the midpoint line is drawn in the right place
- function getABAEdgeIntersections(dim, limit0, limit1) {
- return function(pt1, pt2) {
- var ptInt1 = onlyConstrainedPoint(pt1);
- var ptInt2 = onlyConstrainedPoint(pt2);
-
- var out = [];
- if(ptInt1 && ptInt2 && sameEdge(ptInt1, ptInt2)) return out;
-
- if(ptInt1) out.push(ptInt1);
- if(ptInt2) out.push(ptInt2);
-
- var midShift = 2 * Lib.constrain((pt1[dim] + pt2[dim]) / 2, limit0, limit1) -
- ((ptInt1 || pt1)[dim] + (ptInt2 || pt2)[dim]);
- if(midShift) {
- var ptToAlter;
- if(ptInt1 && ptInt2) {
- ptToAlter = (midShift > 0 === ptInt1[dim] > ptInt2[dim]) ? ptInt1 : ptInt2;
- } else ptToAlter = ptInt1 || ptInt2;
-
- ptToAlter[dim] += midShift;
- }
-
- return out;
- };
- }
-
- var getEdgeIntersections;
- if(shape === 'linear' || shape === 'spline') {
- getEdgeIntersections = getLinearEdgeIntersections;
- } else if(shape === 'hv' || shape === 'vh') {
- getEdgeIntersections = getHVEdgeIntersections;
- } else if(shape === 'hvh') getEdgeIntersections = getABAEdgeIntersections(0, xEdge0, xEdge1);
- else if(shape === 'vhv') getEdgeIntersections = getABAEdgeIntersections(1, yEdge0, yEdge1);
-
- // a segment pt1->pt2 entirely outside the nearby region:
- // find the corner it gets closest to touching
- function getClosestCorner(pt1, pt2) {
- var dx = pt2[0] - pt1[0];
- var m = (pt2[1] - pt1[1]) / dx;
- var b = (pt1[1] * pt2[0] - pt2[1] * pt1[0]) / dx;
-
- if(b > 0) return [m > 0 ? xEdge0 : xEdge1, yEdge1];
- else return [m > 0 ? xEdge1 : xEdge0, yEdge0];
- }
-
- function updateEdge(pt) {
- var x = pt[0];
- var y = pt[1];
- var xSame = x === pts[pti - 1][0];
- var ySame = y === pts[pti - 1][1];
- // duplicate point?
- if(xSame && ySame) return;
- if(pti > 1) {
- // backtracking along an edge?
- var xSame2 = x === pts[pti - 2][0];
- var ySame2 = y === pts[pti - 2][1];
- if(xSame && (x === xEdge0 || x === xEdge1) && xSame2) {
- if(ySame2) pti--; // backtracking exactly - drop prev pt and don't add
- else pts[pti - 1] = pt; // not exact: replace the prev pt
- } else if(ySame && (y === yEdge0 || y === yEdge1) && ySame2) {
- if(xSame2) pti--;
- else pts[pti - 1] = pt;
- } else pts[pti++] = pt;
- } else pts[pti++] = pt;
- }
-
- function updateEdgesForReentry(pt) {
- // if we're outside the nearby region and going back in,
- // we may need to loop around a corner point
- if(pts[pti - 1][0] !== pt[0] && pts[pti - 1][1] !== pt[1]) {
- updateEdge([lastXEdge, lastYEdge]);
- }
- updateEdge(pt);
- lastFarPt = null;
- lastXEdge = lastYEdge = 0;
- }
-
- function addPt(pt) {
- latestXFrac = pt[0] / xLen;
- latestYFrac = pt[1] / yLen;
- // Are we more than maxScreensAway off-screen any direction?
- // if so, clip to this box, but in such a way that on-screen
- // drawing is unchanged
- xEdge = (pt[0] < xEdge0) ? xEdge0 : (pt[0] > xEdge1) ? xEdge1 : 0;
- yEdge = (pt[1] < yEdge0) ? yEdge0 : (pt[1] > yEdge1) ? yEdge1 : 0;
- if(xEdge || yEdge) {
- if(!pti) {
- // to get fills right - if first point is far, push it toward the
- // screen in whichever direction(s) are far
-
- pts[pti++] = [xEdge || pt[0], yEdge || pt[1]];
- } else if(lastFarPt) {
- // both this point and the last are outside the nearby region
- // check if we're crossing the nearby region
- var intersections = getEdgeIntersections(lastFarPt, pt);
- if(intersections.length > 1) {
- updateEdgesForReentry(intersections[0]);
- pts[pti++] = intersections[1];
- }
- } else {
- // we're leaving the nearby region - add the point where we left it
-
- edgePt = getEdgeIntersections(pts[pti - 1], pt)[0];
- pts[pti++] = edgePt;
- }
-
- var lastPt = pts[pti - 1];
- if(xEdge && yEdge && (lastPt[0] !== xEdge || lastPt[1] !== yEdge)) {
- // we've gone out beyond a new corner: add the corner too
- // so that the next point will take the right winding
- if(lastFarPt) {
- if(lastXEdge !== xEdge && lastYEdge !== yEdge) {
- if(lastXEdge && lastYEdge) {
- // we've gone around to an opposite corner - we
- // need to add the correct extra corner
- // in order to get the right winding
- updateEdge(getClosestCorner(lastFarPt, pt));
- } else {
- // we're coming from a far edge - the extra corner
- // we need is determined uniquely by the sectors
- updateEdge([lastXEdge || xEdge, lastYEdge || yEdge]);
- }
- } else if(lastXEdge && lastYEdge) {
- updateEdge([lastXEdge, lastYEdge]);
- }
- }
- updateEdge([xEdge, yEdge]);
- } else if((lastXEdge - xEdge) && (lastYEdge - yEdge)) {
- // we're coming from an edge or far corner to an edge - again the
- // extra corner we need is uniquely determined by the sectors
- updateEdge([xEdge || lastXEdge, yEdge || lastYEdge]);
- }
- lastFarPt = pt;
- lastXEdge = xEdge;
- lastYEdge = yEdge;
- } else {
- if(lastFarPt) {
- // this point is in range but the previous wasn't: add its entry pt first
- updateEdgesForReentry(getEdgeIntersections(lastFarPt, pt)[0]);
- }
-
- pts[pti++] = pt;
- }
- }
-
- // loop over ALL points in this trace
- for(i = 0; i < len; i++) {
- clusterStartPt = getPt(i);
- if(!clusterStartPt) continue;
-
- pti = 0;
- lastFarPt = null;
- addPt(clusterStartPt);
-
- // loop over one segment of the trace
- for(i++; i < len; i++) {
- clusterHighPt = getPt(i);
- if(!clusterHighPt) {
- if(connectGaps) continue;
- else break;
- }
-
- // can't decimate if nonlinear line shape
- // TODO: we *could* decimate [hv]{2,3} shapes if we restricted clusters to horz or vert again
- // but spline would be verrry awkward to decimate
- if(!linear || !opts.simplify) {
- addPt(clusterHighPt);
- continue;
- }
-
- var nextPt = getPt(i + 1);
-
- clusterRefDist = ptDist(clusterHighPt, clusterStartPt);
-
- // #3147 - always include the very first and last points for fills
- if(!(fill && (pti === 0 || pti === len - 1)) &&
- clusterRefDist < getTolerance(clusterHighPt, nextPt) * minTolerance) continue;
-
- clusterUnitVector = [
- (clusterHighPt[0] - clusterStartPt[0]) / clusterRefDist,
- (clusterHighPt[1] - clusterStartPt[1]) / clusterRefDist
- ];
-
- clusterLowPt = clusterStartPt;
- clusterHighVal = clusterRefDist;
- clusterLowVal = clusterMinDeviation = clusterMaxDeviation = 0;
- clusterHighFirst = false;
- clusterEndPt = clusterHighPt;
-
- // loop over one cluster of points that collapse onto one line
- for(i++; i < d.length; i++) {
- thisPt = nextPt;
- nextPt = getPt(i + 1);
- if(!thisPt) {
- if(connectGaps) continue;
- else break;
- }
- thisVector = [
- thisPt[0] - clusterStartPt[0],
- thisPt[1] - clusterStartPt[1]
- ];
- // cross product (or dot with normal to the cluster vector)
- thisDeviation = thisVector[0] * clusterUnitVector[1] - thisVector[1] * clusterUnitVector[0];
- clusterMinDeviation = Math.min(clusterMinDeviation, thisDeviation);
- clusterMaxDeviation = Math.max(clusterMaxDeviation, thisDeviation);
-
- if(clusterMaxDeviation - clusterMinDeviation > getTolerance(thisPt, nextPt)) break;
-
- clusterEndPt = thisPt;
- thisVal = thisVector[0] * clusterUnitVector[0] + thisVector[1] * clusterUnitVector[1];
-
- if(thisVal > clusterHighVal) {
- clusterHighVal = thisVal;
- clusterHighPt = thisPt;
- clusterHighFirst = false;
- } else if(thisVal < clusterLowVal) {
- clusterLowVal = thisVal;
- clusterLowPt = thisPt;
- clusterHighFirst = true;
- }
- }
-
- // insert this cluster into pts
- // we've already inserted the start pt, now check if we have high and low pts
- if(clusterHighFirst) {
- addPt(clusterHighPt);
- if(clusterEndPt !== clusterLowPt) addPt(clusterLowPt);
- } else {
- if(clusterLowPt !== clusterStartPt) addPt(clusterLowPt);
- if(clusterEndPt !== clusterHighPt) addPt(clusterHighPt);
- }
- // and finally insert the end pt
- addPt(clusterEndPt);
-
- // have we reached the end of this segment?
- if(i >= d.length || !thisPt) break;
-
- // otherwise we have an out-of-cluster point to insert as next clusterStartPt
- addPt(thisPt);
- clusterStartPt = thisPt;
- }
-
- // to get fills right - repeat what we did at the start
- if(lastFarPt) updateEdge([lastXEdge || lastFarPt[0], lastYEdge || lastFarPt[1]]);
-
- segments.push(pts.slice(0, pti));
- }
-
- return segments;
-};
-
-},{"../../constants/numerical":149,"../../lib":168,"./constants":369}],379:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-
-// common to 'scatter' and 'scatterternary'
-module.exports = function handleLineShapeDefaults(traceIn, traceOut, coerce) {
- var shape = coerce('line.shape');
- if(shape === 'spline') coerce('line.smoothing');
-};
-
-},{}],380:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var LINKEDFILLS = {tonextx: 1, tonexty: 1, tonext: 1};
-
-module.exports = function linkTraces(gd, plotinfo, cdscatter) {
- var trace, i, group, prevtrace, groupIndex;
-
- // first sort traces to keep stacks & filled-together groups together
- var groupIndices = {};
- var needsSort = false;
- var prevGroupIndex = -1;
- var nextGroupIndex = 0;
- var prevUnstackedGroupIndex = -1;
- for(i = 0; i < cdscatter.length; i++) {
- trace = cdscatter[i][0].trace;
- group = trace.stackgroup || '';
- if(group) {
- if(group in groupIndices) {
- groupIndex = groupIndices[group];
- } else {
- groupIndex = groupIndices[group] = nextGroupIndex;
- nextGroupIndex++;
- }
- } else if(trace.fill in LINKEDFILLS && prevUnstackedGroupIndex >= 0) {
- groupIndex = prevUnstackedGroupIndex;
- } else {
- groupIndex = prevUnstackedGroupIndex = nextGroupIndex;
- nextGroupIndex++;
- }
-
- if(groupIndex < prevGroupIndex) needsSort = true;
- trace._groupIndex = prevGroupIndex = groupIndex;
- }
-
- var cdscatterSorted = cdscatter.slice();
- if(needsSort) {
- cdscatterSorted.sort(function(a, b) {
- var traceA = a[0].trace;
- var traceB = b[0].trace;
- return (traceA._groupIndex - traceB._groupIndex) ||
- (traceA.index - traceB.index);
- });
- }
-
- // now link traces to each other
- var prevtraces = {};
- for(i = 0; i < cdscatterSorted.length; i++) {
- trace = cdscatterSorted[i][0].trace;
- group = trace.stackgroup || '';
-
- // Note: The check which ensures all cdscatter here are for the same axis and
- // are either cartesian or scatterternary has been removed. This code assumes
- // the passed scattertraces have been filtered to the proper plot types and
- // the proper subplots.
- if(trace.visible === true) {
- trace._nexttrace = null;
-
- if(trace.fill in LINKEDFILLS) {
- prevtrace = prevtraces[group];
- trace._prevtrace = prevtrace || null;
-
- if(prevtrace) {
- prevtrace._nexttrace = trace;
- }
- }
-
- trace._ownfill = (trace.fill && (
- trace.fill.substr(0, 6) === 'tozero' ||
- trace.fill === 'toself' ||
- (trace.fill.substr(0, 2) === 'to' && !trace._prevtrace)
- ));
-
- prevtraces[group] = trace;
- } else {
- trace._prevtrace = trace._nexttrace = trace._ownfill = null;
- }
- }
-
- return cdscatterSorted;
-};
-
-},{}],381:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var isNumeric = _dereq_('fast-isnumeric');
-
-
-// used in the drawing step for 'scatter' and 'scattegeo' and
-// in the convert step for 'scatter3d'
-module.exports = function makeBubbleSizeFn(trace) {
- var marker = trace.marker;
- var sizeRef = marker.sizeref || 1;
- var sizeMin = marker.sizemin || 0;
-
- // for bubble charts, allow scaling the provided value linearly
- // and by area or diameter.
- // Note this only applies to the array-value sizes
-
- var baseFn = (marker.sizemode === 'area') ?
- function(v) { return Math.sqrt(v / sizeRef); } :
- function(v) { return v / sizeRef; };
-
- // TODO add support for position/negative bubbles?
- // TODO add 'sizeoffset' attribute?
- return function(v) {
- var baseSize = baseFn(v / 2);
-
- // don't show non-numeric and negative sizes
- return (isNumeric(baseSize) && (baseSize > 0)) ?
- Math.max(baseSize, sizeMin) :
- 0;
- };
-};
-
-},{"fast-isnumeric":18}],382:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-module.exports = {
- container: 'marker',
- min: 'cmin',
- max: 'cmax'
-};
-
-},{}],383:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Color = _dereq_('../../components/color');
-var hasColorscale = _dereq_('../../components/colorscale/helpers').hasColorscale;
-var colorscaleDefaults = _dereq_('../../components/colorscale/defaults');
-
-var subTypes = _dereq_('./subtypes');
-
-/*
- * opts: object of flags to control features not all marker users support
- * noLine: caller does not support marker lines
- * gradient: caller supports gradients
- * noSelect: caller does not support selected/unselected attribute containers
- */
-module.exports = function markerDefaults(traceIn, traceOut, defaultColor, layout, coerce, opts) {
- var isBubble = subTypes.isBubble(traceIn);
- var lineColor = (traceIn.line || {}).color;
- var defaultMLC;
-
- opts = opts || {};
-
- // marker.color inherit from line.color (even if line.color is an array)
- if(lineColor) defaultColor = lineColor;
-
- coerce('marker.symbol');
- coerce('marker.opacity', isBubble ? 0.7 : 1);
- coerce('marker.size');
-
- coerce('marker.color', defaultColor);
- if(hasColorscale(traceIn, 'marker')) {
- colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'marker.', cLetter: 'c'});
- }
-
- if(!opts.noSelect) {
- coerce('selected.marker.color');
- coerce('unselected.marker.color');
- coerce('selected.marker.size');
- coerce('unselected.marker.size');
- }
-
- if(!opts.noLine) {
- // if there's a line with a different color than the marker, use
- // that line color as the default marker line color
- // (except when it's an array)
- // mostly this is for transparent markers to behave nicely
- if(lineColor && !Array.isArray(lineColor) && (traceOut.marker.color !== lineColor)) {
- defaultMLC = lineColor;
- } else if(isBubble) defaultMLC = Color.background;
- else defaultMLC = Color.defaultLine;
-
- coerce('marker.line.color', defaultMLC);
- if(hasColorscale(traceIn, 'marker.line')) {
- colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'marker.line.', cLetter: 'c'});
- }
-
- coerce('marker.line.width', isBubble ? 1 : 0);
- }
-
- if(isBubble) {
- coerce('marker.sizeref');
- coerce('marker.sizemin');
- coerce('marker.sizemode');
- }
-
- if(opts.gradient) {
- var gradientType = coerce('marker.gradient.type');
- if(gradientType !== 'none') {
- coerce('marker.gradient.color');
- }
- }
-};
-
-},{"../../components/color":51,"../../components/colorscale/defaults":61,"../../components/colorscale/helpers":62,"./subtypes":388}],384:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var d3 = _dereq_('d3');
-
-var Registry = _dereq_('../../registry');
-var Lib = _dereq_('../../lib');
-var ensureSingle = Lib.ensureSingle;
-var identity = Lib.identity;
-var Drawing = _dereq_('../../components/drawing');
-
-var subTypes = _dereq_('./subtypes');
-var linePoints = _dereq_('./line_points');
-var linkTraces = _dereq_('./link_traces');
-var polygonTester = _dereq_('../../lib/polygon').tester;
-
-module.exports = function plot(gd, plotinfo, cdscatter, scatterLayer, transitionOpts, makeOnCompleteCallback) {
- var join, onComplete;
-
- // If transition config is provided, then it is only a partial replot and traces not
- // updated are removed.
- var isFullReplot = !transitionOpts;
- var hasTransition = !!transitionOpts && transitionOpts.duration > 0;
-
- // Link traces so the z-order of fill layers is correct
- var cdscatterSorted = linkTraces(gd, plotinfo, cdscatter);
-
- join = scatterLayer.selectAll('g.trace')
- .data(cdscatterSorted, function(d) { return d[0].trace.uid; });
-
- // Append new traces:
- join.enter().append('g')
- .attr('class', function(d) {
- return 'trace scatter trace' + d[0].trace.uid;
- })
- .style('stroke-miterlimit', 2);
- join.order();
-
- createFills(gd, join, plotinfo);
-
- if(hasTransition) {
- if(makeOnCompleteCallback) {
- // If it was passed a callback to register completion, make a callback. If
- // this is created, then it must be executed on completion, otherwise the
- // pos-transition redraw will not execute:
- onComplete = makeOnCompleteCallback();
- }
-
- var transition = d3.transition()
- .duration(transitionOpts.duration)
- .ease(transitionOpts.easing)
- .each('end', function() {
- onComplete && onComplete();
- })
- .each('interrupt', function() {
- onComplete && onComplete();
- });
-
- transition.each(function() {
- // Must run the selection again since otherwise enters/updates get grouped together
- // and these get executed out of order. Except we need them in order!
- scatterLayer.selectAll('g.trace').each(function(d, i) {
- plotOne(gd, i, plotinfo, d, cdscatterSorted, this, transitionOpts);
- });
- });
- } else {
- join.each(function(d, i) {
- plotOne(gd, i, plotinfo, d, cdscatterSorted, this, transitionOpts);
- });
- }
-
- if(isFullReplot) {
- join.exit().remove();
- }
-
- // remove paths that didn't get used
- scatterLayer.selectAll('path:not([d])').remove();
-};
-
-function createFills(gd, traceJoin, plotinfo) {
- traceJoin.each(function(d) {
- var fills = ensureSingle(d3.select(this), 'g', 'fills');
- Drawing.setClipUrl(fills, plotinfo.layerClipId, gd);
-
- var trace = d[0].trace;
-
- var fillData = [];
- if(trace._ownfill) fillData.push('_ownFill');
- if(trace._nexttrace) fillData.push('_nextFill');
-
- var fillJoin = fills.selectAll('g').data(fillData, identity);
-
- fillJoin.enter().append('g');
-
- fillJoin.exit()
- .each(function(d) { trace[d] = null; })
- .remove();
-
- fillJoin.order().each(function(d) {
- // make a path element inside the fill group, just so
- // we can give it its own data later on and the group can
- // keep its simple '_*Fill' data
- trace[d] = ensureSingle(d3.select(this), 'path', 'js-fill');
- });
- });
-}
-
-function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transitionOpts) {
- var i;
-
- // Since this has been reorganized and we're executing this on individual traces,
- // we need to pass it the full list of cdscatter as well as this trace's index (idx)
- // since it does an internal n^2 loop over comparisons with other traces:
- selectMarkers(gd, idx, plotinfo, cdscatter, cdscatterAll);
-
- var hasTransition = !!transitionOpts && transitionOpts.duration > 0;
-
- function transition(selection) {
- return hasTransition ? selection.transition() : selection;
- }
-
- var xa = plotinfo.xaxis;
- var ya = plotinfo.yaxis;
-
- var trace = cdscatter[0].trace;
- var line = trace.line;
- var tr = d3.select(element);
-
- var errorBarGroup = ensureSingle(tr, 'g', 'errorbars');
- var lines = ensureSingle(tr, 'g', 'lines');
- var points = ensureSingle(tr, 'g', 'points');
- var text = ensureSingle(tr, 'g', 'text');
-
- // error bars are at the bottom
- Registry.getComponentMethod('errorbars', 'plot')(gd, errorBarGroup, plotinfo, transitionOpts);
-
- if(trace.visible !== true) return;
-
- transition(tr).style('opacity', trace.opacity);
-
- // BUILD LINES AND FILLS
- var ownFillEl3, tonext;
- var ownFillDir = trace.fill.charAt(trace.fill.length - 1);
- if(ownFillDir !== 'x' && ownFillDir !== 'y') ownFillDir = '';
-
- // store node for tweaking by selectPoints
- if(!plotinfo.isRangePlot) cdscatter[0].node3 = tr;
-
- var prevRevpath = '';
- var prevPolygons = [];
- var prevtrace = trace._prevtrace;
-
- if(prevtrace) {
- prevRevpath = prevtrace._prevRevpath || '';
- tonext = prevtrace._nextFill;
- prevPolygons = prevtrace._polygons;
- }
-
- var thispath;
- var thisrevpath;
- // fullpath is all paths for this curve, joined together straight
- // across gaps, for filling
- var fullpath = '';
- // revpath is fullpath reversed, for fill-to-next
- var revpath = '';
- // functions for converting a point array to a path
- var pathfn, revpathbase, revpathfn;
- // variables used before and after the data join
- var pt0, lastSegment, pt1, thisPolygons;
-
- // initialize line join data / method
- var segments = [];
- var makeUpdate = Lib.noop;
-
- ownFillEl3 = trace._ownFill;
-
- if(subTypes.hasLines(trace) || trace.fill !== 'none') {
- if(tonext) {
- // This tells .style which trace to use for fill information:
- tonext.datum(cdscatter);
- }
-
- if(['hv', 'vh', 'hvh', 'vhv'].indexOf(line.shape) !== -1) {
- pathfn = Drawing.steps(line.shape);
- revpathbase = Drawing.steps(
- line.shape.split('').reverse().join('')
- );
- } else if(line.shape === 'spline') {
- pathfn = revpathbase = function(pts) {
- var pLast = pts[pts.length - 1];
- if(pts.length > 1 && pts[0][0] === pLast[0] && pts[0][1] === pLast[1]) {
- // identical start and end points: treat it as a
- // closed curve so we don't get a kink
- return Drawing.smoothclosed(pts.slice(1), line.smoothing);
- } else {
- return Drawing.smoothopen(pts, line.smoothing);
- }
- };
- } else {
- pathfn = revpathbase = function(pts) {
- return 'M' + pts.join('L');
- };
- }
-
- revpathfn = function(pts) {
- // note: this is destructive (reverses pts in place) so can't use pts after this
- return revpathbase(pts.reverse());
- };
-
- segments = linePoints(cdscatter, {
- xaxis: xa,
- yaxis: ya,
- connectGaps: trace.connectgaps,
- baseTolerance: Math.max(line.width || 1, 3) / 4,
- shape: line.shape,
- simplify: line.simplify,
- fill: trace.fill
- });
-
- // since we already have the pixel segments here, use them to make
- // polygons for hover on fill
- // TODO: can we skip this if hoveron!=fills? That would mean we
- // need to redraw when you change hoveron...
- thisPolygons = trace._polygons = new Array(segments.length);
- for(i = 0; i < segments.length; i++) {
- trace._polygons[i] = polygonTester(segments[i]);
- }
-
- if(segments.length) {
- pt0 = segments[0][0];
- lastSegment = segments[segments.length - 1];
- pt1 = lastSegment[lastSegment.length - 1];
- }
-
- makeUpdate = function(isEnter) {
- return function(pts) {
- thispath = pathfn(pts);
- thisrevpath = revpathfn(pts);
- if(!fullpath) {
- fullpath = thispath;
- revpath = thisrevpath;
- } else if(ownFillDir) {
- fullpath += 'L' + thispath.substr(1);
- revpath = thisrevpath + ('L' + revpath.substr(1));
- } else {
- fullpath += 'Z' + thispath;
- revpath = thisrevpath + 'Z' + revpath;
- }
-
- if(subTypes.hasLines(trace) && pts.length > 1) {
- var el = d3.select(this);
-
- // This makes the coloring work correctly:
- el.datum(cdscatter);
-
- if(isEnter) {
- transition(el.style('opacity', 0)
- .attr('d', thispath)
- .call(Drawing.lineGroupStyle))
- .style('opacity', 1);
- } else {
- var sel = transition(el);
- sel.attr('d', thispath);
- Drawing.singleLineStyle(cdscatter, sel);
- }
- }
- };
- };
- }
-
- var lineJoin = lines.selectAll('.js-line').data(segments);
-
- transition(lineJoin.exit())
- .style('opacity', 0)
- .remove();
-
- lineJoin.each(makeUpdate(false));
-
- lineJoin.enter().append('path')
- .classed('js-line', true)
- .style('vector-effect', 'non-scaling-stroke')
- .call(Drawing.lineGroupStyle)
- .each(makeUpdate(true));
-
- Drawing.setClipUrl(lineJoin, plotinfo.layerClipId, gd);
-
- function clearFill(selection) {
- transition(selection).attr('d', 'M0,0Z');
- }
-
- if(segments.length) {
- if(ownFillEl3) {
- ownFillEl3.datum(cdscatter);
- if(pt0 && pt1) {
- if(ownFillDir) {
- if(ownFillDir === 'y') {
- pt0[1] = pt1[1] = ya.c2p(0, true);
- } else if(ownFillDir === 'x') {
- pt0[0] = pt1[0] = xa.c2p(0, true);
- }
-
- // fill to zero: full trace path, plus extension of
- // the endpoints to the appropriate axis
- // For the sake of animations, wrap the points around so that
- // the points on the axes are the first two points. Otherwise
- // animations get a little crazy if the number of points changes.
- transition(ownFillEl3).attr('d', 'M' + pt1 + 'L' + pt0 + 'L' + fullpath.substr(1))
- .call(Drawing.singleFillStyle);
- } else {
- // fill to self: just join the path to itself
- transition(ownFillEl3).attr('d', fullpath + 'Z')
- .call(Drawing.singleFillStyle);
- }
- }
- } else if(tonext) {
- if(trace.fill.substr(0, 6) === 'tonext' && fullpath && prevRevpath) {
- // fill to next: full trace path, plus the previous path reversed
- if(trace.fill === 'tonext') {
- // tonext: for use by concentric shapes, like manually constructed
- // contours, we just add the two paths closed on themselves.
- // This makes strange results if one path is *not* entirely
- // inside the other, but then that is a strange usage.
- transition(tonext).attr('d', fullpath + 'Z' + prevRevpath + 'Z')
- .call(Drawing.singleFillStyle);
- } else {
- // tonextx/y: for now just connect endpoints with lines. This is
- // the correct behavior if the endpoints are at the same value of
- // y/x, but if they *aren't*, we should ideally do more complicated
- // things depending on whether the new endpoint projects onto the
- // existing curve or off the end of it
- transition(tonext).attr('d', fullpath + 'L' + prevRevpath.substr(1) + 'Z')
- .call(Drawing.singleFillStyle);
- }
- trace._polygons = trace._polygons.concat(prevPolygons);
- } else {
- clearFill(tonext);
- trace._polygons = null;
- }
- }
- trace._prevRevpath = revpath;
- trace._prevPolygons = thisPolygons;
- } else {
- if(ownFillEl3) clearFill(ownFillEl3);
- else if(tonext) clearFill(tonext);
- trace._polygons = trace._prevRevpath = trace._prevPolygons = null;
- }
-
-
- function visFilter(d) {
- return d.filter(function(v) { return !v.gap && v.vis; });
- }
-
- function visFilterWithGaps(d) {
- return d.filter(function(v) { return v.vis; });
- }
-
- function gapFilter(d) {
- return d.filter(function(v) { return !v.gap; });
- }
-
- function keyFunc(d) {
- return d.id;
- }
-
- // Returns a function if the trace is keyed, otherwise returns undefined
- function getKeyFunc(trace) {
- if(trace.ids) {
- return keyFunc;
- }
- }
-
- function hideFilter() {
- return false;
- }
-
- function makePoints(points, text, cdscatter) {
- var join, selection, hasNode;
-
- var trace = cdscatter[0].trace;
- var showMarkers = subTypes.hasMarkers(trace);
- var showText = subTypes.hasText(trace);
-
- var keyFunc = getKeyFunc(trace);
- var markerFilter = hideFilter;
- var textFilter = hideFilter;
-
- if(showMarkers || showText) {
- var showFilter = identity;
- // if we're stacking, "infer zero" gap mode gets markers in the
- // gap points - because we've inferred a zero there - but other
- // modes (currently "interpolate", later "interrupt" hopefully)
- // we don't draw generated markers
- var stackGroup = trace.stackgroup;
- var isInferZero = stackGroup && (
- gd._fullLayout._scatterStackOpts[xa._id + ya._id][stackGroup].stackgaps === 'infer zero');
- if(trace.marker.maxdisplayed || trace._needsCull) {
- showFilter = isInferZero ? visFilterWithGaps : visFilter;
- } else if(stackGroup && !isInferZero) {
- showFilter = gapFilter;
- }
-
- if(showMarkers) markerFilter = showFilter;
- if(showText) textFilter = showFilter;
- }
-
- // marker points
-
- selection = points.selectAll('path.point');
-
- join = selection.data(markerFilter, keyFunc);
-
- var enter = join.enter().append('path')
- .classed('point', true);
-
- if(hasTransition) {
- enter
- .call(Drawing.pointStyle, trace, gd)
- .call(Drawing.translatePoints, xa, ya)
- .style('opacity', 0)
- .transition()
- .style('opacity', 1);
- }
-
- join.order();
-
- var styleFns;
- if(showMarkers) {
- styleFns = Drawing.makePointStyleFns(trace);
- }
-
- join.each(function(d) {
- var el = d3.select(this);
- var sel = transition(el);
- hasNode = Drawing.translatePoint(d, sel, xa, ya);
-
- if(hasNode) {
- Drawing.singlePointStyle(d, sel, trace, styleFns, gd);
-
- if(plotinfo.layerClipId) {
- Drawing.hideOutsideRangePoint(d, sel, xa, ya, trace.xcalendar, trace.ycalendar);
- }
-
- if(trace.customdata) {
- el.classed('plotly-customdata', d.data !== null && d.data !== undefined);
- }
- } else {
- sel.remove();
- }
- });
-
- if(hasTransition) {
- join.exit().transition()
- .style('opacity', 0)
- .remove();
- } else {
- join.exit().remove();
- }
-
- // text points
- selection = text.selectAll('g');
- join = selection.data(textFilter, keyFunc);
-
- // each text needs to go in its own 'g' in case
- // it gets converted to mathjax
- join.enter().append('g').classed('textpoint', true).append('text');
-
- join.order();
-
- join.each(function(d) {
- var g = d3.select(this);
- var sel = transition(g.select('text'));
- hasNode = Drawing.translatePoint(d, sel, xa, ya);
-
- if(hasNode) {
- if(plotinfo.layerClipId) {
- Drawing.hideOutsideRangePoint(d, g, xa, ya, trace.xcalendar, trace.ycalendar);
- }
- } else {
- g.remove();
- }
- });
-
- join.selectAll('text')
- .call(Drawing.textPointStyle, trace, gd)
- .each(function(d) {
- // This just *has* to be totally custom becuase of SVG text positioning :(
- // It's obviously copied from translatePoint; we just can't use that
- var x = xa.c2p(d.x);
- var y = ya.c2p(d.y);
-
- d3.select(this).selectAll('tspan.line').each(function() {
- transition(d3.select(this)).attr({x: x, y: y});
- });
- });
-
- join.exit().remove();
- }
-
- points.datum(cdscatter);
- text.datum(cdscatter);
- makePoints(points, text, cdscatter);
-
- // lastly, clip points groups of `cliponaxis !== false` traces
- // on `plotinfo._hasClipOnAxisFalse === true` subplots
- var hasClipOnAxisFalse = trace.cliponaxis === false;
- var clipUrl = hasClipOnAxisFalse ? null : plotinfo.layerClipId;
- Drawing.setClipUrl(points, clipUrl, gd);
- Drawing.setClipUrl(text, clipUrl, gd);
-}
-
-function selectMarkers(gd, idx, plotinfo, cdscatter, cdscatterAll) {
- var xa = plotinfo.xaxis;
- var ya = plotinfo.yaxis;
- var xr = d3.extent(Lib.simpleMap(xa.range, xa.r2c));
- var yr = d3.extent(Lib.simpleMap(ya.range, ya.r2c));
-
- var trace = cdscatter[0].trace;
- if(!subTypes.hasMarkers(trace)) return;
- // if marker.maxdisplayed is used, select a maximum of
- // mnum markers to show, from the set that are in the viewport
- var mnum = trace.marker.maxdisplayed;
-
- // TODO: remove some as we get away from the viewport?
- if(mnum === 0) return;
-
- var cd = cdscatter.filter(function(v) {
- return v.x >= xr[0] && v.x <= xr[1] && v.y >= yr[0] && v.y <= yr[1];
- });
- var inc = Math.ceil(cd.length / mnum);
- var tnum = 0;
- cdscatterAll.forEach(function(cdj, j) {
- var tracei = cdj[0].trace;
- if(subTypes.hasMarkers(tracei) &&
- tracei.marker.maxdisplayed > 0 && j < idx) {
- tnum++;
- }
- });
-
- // if multiple traces use maxdisplayed, stagger which markers we
- // display this formula offsets successive traces by 1/3 of the
- // increment, adding an extra small amount after each triplet so
- // it's not quite periodic
- var i0 = Math.round(tnum * inc / 3 + Math.floor(tnum / 3) * inc / 7.1);
-
- // for error bars: save in cd which markers to show
- // so we don't have to repeat this
- cdscatter.forEach(function(v) { delete v.vis; });
- cd.forEach(function(v, i) {
- if(Math.round((i + i0) % inc) === 0) v.vis = true;
- });
-}
-
-},{"../../components/drawing":72,"../../lib":168,"../../lib/polygon":180,"../../registry":256,"./line_points":378,"./link_traces":380,"./subtypes":388,"d3":16}],385:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var subtypes = _dereq_('./subtypes');
-
-module.exports = function selectPoints(searchInfo, selectionTester) {
- var cd = searchInfo.cd;
- var xa = searchInfo.xaxis;
- var ya = searchInfo.yaxis;
- var selection = [];
- var trace = cd[0].trace;
- var i;
- var di;
- var x;
- var y;
-
- var hasOnlyLines = (!subtypes.hasMarkers(trace) && !subtypes.hasText(trace));
- if(hasOnlyLines) return [];
-
- if(selectionTester === false) { // clear selection
- for(i = 0; i < cd.length; i++) {
- cd[i].selected = 0;
- }
- } else {
- for(i = 0; i < cd.length; i++) {
- di = cd[i];
- x = xa.c2p(di.x);
- y = ya.c2p(di.y);
-
- if((di.i !== null) && selectionTester.contains([x, y], false, i, searchInfo)) {
- selection.push({
- pointNumber: di.i,
- x: xa.c2d(di.x),
- y: ya.c2d(di.y)
- });
- di.selected = 1;
- } else {
- di.selected = 0;
- }
- }
- }
-
- return selection;
-};
-
-},{"./subtypes":388}],386:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var perStackAttrs = ['orientation', 'groupnorm', 'stackgaps'];
-
-module.exports = function handleStackDefaults(traceIn, traceOut, layout, coerce) {
- var stackOpts = layout._scatterStackOpts;
-
- var stackGroup = coerce('stackgroup');
- if(stackGroup) {
- // use independent stacking options per subplot
- var subplot = traceOut.xaxis + traceOut.yaxis;
- var subplotStackOpts = stackOpts[subplot];
- if(!subplotStackOpts) subplotStackOpts = stackOpts[subplot] = {};
-
- var groupOpts = subplotStackOpts[stackGroup];
- var firstTrace = false;
- if(groupOpts) {
- groupOpts.traces.push(traceOut);
- } else {
- groupOpts = subplotStackOpts[stackGroup] = {
- // keep track of trace indices for use during stacking calculations
- // this will be filled in during `calc` and used during `crossTraceCalc`
- // so it's OK if we don't recreate it during a non-calc edit
- traceIndices: [],
- // Hold on to the whole set of prior traces
- // First one is most important, so we can clear defaults
- // there if we find explicit values only in later traces.
- // We're only going to *use* the values stored in groupOpts,
- // but for the editor and validate we want things self-consistent
- // The full set of traces is used only to fix `fill` default if
- // we find `orientation: 'h'` beyond the first trace
- traces: [traceOut]
- };
- firstTrace = true;
- }
- // TODO: how is this going to work with groupby transforms?
- // in principle it should be OK I guess, as long as explicit group styles
- // don't override explicit base-trace styles?
-
- var dflts = {
- orientation: (traceOut.x && !traceOut.y) ? 'h' : 'v'
- };
-
- for(var i = 0; i < perStackAttrs.length; i++) {
- var attr = perStackAttrs[i];
- var attrFound = attr + 'Found';
- if(!groupOpts[attrFound]) {
- var traceHasAttr = traceIn[attr] !== undefined;
- var isOrientation = attr === 'orientation';
- if(traceHasAttr || firstTrace) {
- groupOpts[attr] = coerce(attr, dflts[attr]);
-
- if(isOrientation) {
- groupOpts.fillDflt = groupOpts[attr] === 'h' ?
- 'tonextx' : 'tonexty';
- }
-
- if(traceHasAttr) {
- // Note: this will show a value here even if it's invalid
- // in which case it will revert to default.
- groupOpts[attrFound] = true;
-
- // Note: only one trace in the stack will get a _fullData
- // entry for a given stack-wide attribute. If no traces
- // (or the first trace) specify that attribute, the
- // first trace will get it. If the first trace does NOT
- // specify it but some later trace does, then it gets
- // removed from the first trace and only included in the
- // one that specified it. This is mostly important for
- // editors (that want to see the full values to know
- // what settings are available) and Plotly.react diffing.
- // Editors may want to use fullLayout._scatterStackOpts
- // directly and make these settings available from all
- // traces in the stack... then set the new value into
- // the first trace, and clear all later traces.
- if(!firstTrace) {
- delete groupOpts.traces[0][attr];
-
- // orientation can affect default fill of previous traces
- if(isOrientation) {
- for(var j = 0; j < groupOpts.traces.length - 1; j++) {
- var trace2 = groupOpts.traces[j];
- if(trace2._input.fill !== trace2.fill) {
- trace2.fill = groupOpts.fillDflt;
- }
- }
- }
- }
- }
- }
- }
- }
- return groupOpts;
- }
-};
-
-},{}],387:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var d3 = _dereq_('d3');
-var Drawing = _dereq_('../../components/drawing');
-var Registry = _dereq_('../../registry');
-
-function style(gd, cd) {
- var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.scatter');
-
- s.style('opacity', function(d) {
- return d[0].trace.opacity;
- });
-
- s.selectAll('g.points').each(function(d) {
- var sel = d3.select(this);
- var trace = d.trace || d[0].trace;
- stylePoints(sel, trace, gd);
- });
-
- s.selectAll('g.text').each(function(d) {
- var sel = d3.select(this);
- var trace = d.trace || d[0].trace;
- styleText(sel, trace, gd);
- });
-
- s.selectAll('g.trace path.js-line')
- .call(Drawing.lineGroupStyle);
-
- s.selectAll('g.trace path.js-fill')
- .call(Drawing.fillGroupStyle);
-
- Registry.getComponentMethod('errorbars', 'style')(s);
-}
-
-function stylePoints(sel, trace, gd) {
- Drawing.pointStyle(sel.selectAll('path.point'), trace, gd);
-}
-
-function styleText(sel, trace, gd) {
- Drawing.textPointStyle(sel.selectAll('text'), trace, gd);
-}
-
-function styleOnSelect(gd, cd) {
- var s = cd[0].node3;
- var trace = cd[0].trace;
-
- if(trace.selectedpoints) {
- Drawing.selectedPointStyle(s.selectAll('path.point'), trace);
- Drawing.selectedTextStyle(s.selectAll('text'), trace);
- } else {
- stylePoints(s, trace, gd);
- styleText(s, trace, gd);
- }
-}
-
-module.exports = {
- style: style,
- stylePoints: stylePoints,
- styleText: styleText,
- styleOnSelect: styleOnSelect
-};
-
-},{"../../components/drawing":72,"../../registry":256,"d3":16}],388:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-module.exports = {
- hasLines: function(trace) {
- return trace.visible && trace.mode &&
- trace.mode.indexOf('lines') !== -1;
- },
-
- hasMarkers: function(trace) {
- return trace.visible && (
- (trace.mode && trace.mode.indexOf('markers') !== -1) ||
- // until splom implements 'mode'
- trace.type === 'splom'
- );
- },
-
- hasText: function(trace) {
- return trace.visible && trace.mode &&
- trace.mode.indexOf('text') !== -1;
- },
-
- isBubble: function(trace) {
- return Lib.isPlainObject(trace.marker) &&
- Lib.isArrayOrTypedArray(trace.marker.size);
- }
-};
-
-},{"../../lib":168}],389:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-/*
- * opts: object of flags to control features not all text users support
- * noSelect: caller does not support selected/unselected attribute containers
- */
-module.exports = function(traceIn, traceOut, layout, coerce, opts) {
- opts = opts || {};
-
- coerce('textposition');
- Lib.coerceFont(coerce, 'textfont', layout.font);
-
- if(!opts.noSelect) {
- coerce('selected.textfont.color');
- coerce('unselected.textfont.color');
- }
-};
-
-},{"../../lib":168}],390:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var Registry = _dereq_('../../registry');
-
-module.exports = function handleXYDefaults(traceIn, traceOut, layout, coerce) {
- var x = coerce('x');
- var y = coerce('y');
- var len;
-
- var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults');
- handleCalendarDefaults(traceIn, traceOut, ['x', 'y'], layout);
-
- if(x) {
- var xlen = Lib.minRowLength(x);
- if(y) {
- len = Math.min(xlen, Lib.minRowLength(y));
- } else {
- len = xlen;
- coerce('y0');
- coerce('dy');
- }
- } else {
- if(!y) return 0;
-
- len = Lib.minRowLength(y);
- coerce('x0');
- coerce('dx');
- }
-
- traceOut._length = len;
-
- return len;
-};
-
-},{"../../lib":168,"../../registry":256}],391:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
-var scatterAttrs = _dereq_('../scatter/attributes');
-var plotAttrs = _dereq_('../../plots/attributes');
-var colorScaleAttrs = _dereq_('../../components/colorscale/attributes');
-var dash = _dereq_('../../components/drawing/attributes').dash;
-
-var extendFlat = _dereq_('../../lib/extend').extendFlat;
-
-var scatterMarkerAttrs = scatterAttrs.marker;
-var scatterLineAttrs = scatterAttrs.line;
-var scatterMarkerLineAttrs = scatterMarkerAttrs.line;
-
-module.exports = {
- a: {
- valType: 'data_array',
- editType: 'calc',
-
- },
- b: {
- valType: 'data_array',
- editType: 'calc',
-
- },
- c: {
- valType: 'data_array',
- editType: 'calc',
-
- },
- sum: {
- valType: 'number',
-
- dflt: 0,
- min: 0,
- editType: 'calc',
-
- },
- mode: extendFlat({}, scatterAttrs.mode, {dflt: 'markers'}),
- text: extendFlat({}, scatterAttrs.text, {
-
- }),
- hovertext: extendFlat({}, scatterAttrs.hovertext, {
-
- }),
- line: {
- color: scatterLineAttrs.color,
- width: scatterLineAttrs.width,
- dash: dash,
- shape: extendFlat({}, scatterLineAttrs.shape,
- {values: ['linear', 'spline']}),
- smoothing: scatterLineAttrs.smoothing,
- editType: 'calc'
- },
- connectgaps: scatterAttrs.connectgaps,
- cliponaxis: scatterAttrs.cliponaxis,
- fill: extendFlat({}, scatterAttrs.fill, {
- values: ['none', 'toself', 'tonext'],
- dflt: 'none',
-
- }),
- fillcolor: scatterAttrs.fillcolor,
- marker: extendFlat({
- symbol: scatterMarkerAttrs.symbol,
- opacity: scatterMarkerAttrs.opacity,
- maxdisplayed: scatterMarkerAttrs.maxdisplayed,
- size: scatterMarkerAttrs.size,
- sizeref: scatterMarkerAttrs.sizeref,
- sizemin: scatterMarkerAttrs.sizemin,
- sizemode: scatterMarkerAttrs.sizemode,
- line: extendFlat({
- width: scatterMarkerLineAttrs.width,
- editType: 'calc'
- },
- colorScaleAttrs('marker.line')
- ),
- gradient: scatterMarkerAttrs.gradient,
- editType: 'calc'
- },
- colorScaleAttrs('marker')
- ),
-
- textfont: scatterAttrs.textfont,
- textposition: scatterAttrs.textposition,
-
- selected: scatterAttrs.selected,
- unselected: scatterAttrs.unselected,
-
- hoverinfo: extendFlat({}, plotAttrs.hoverinfo, {
- flags: ['a', 'b', 'c', 'text', 'name']
- }),
- hoveron: scatterAttrs.hoveron,
- hovertemplate: hovertemplateAttrs(),
-};
-
-},{"../../components/colorscale/attributes":58,"../../components/drawing/attributes":71,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../../plots/attributes":209,"../scatter/attributes":365}],392:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var isNumeric = _dereq_('fast-isnumeric');
-
-var calcColorscale = _dereq_('../scatter/colorscale_calc');
-var arraysToCalcdata = _dereq_('../scatter/arrays_to_calcdata');
-var calcSelection = _dereq_('../scatter/calc_selection');
-var calcMarkerSize = _dereq_('../scatter/calc').calcMarkerSize;
-
-var dataArrays = ['a', 'b', 'c'];
-var arraysToFill = {a: ['b', 'c'], b: ['a', 'c'], c: ['a', 'b']};
-
-module.exports = function calc(gd, trace) {
- var ternary = gd._fullLayout[trace.subplot];
- var displaySum = ternary.sum;
- var normSum = trace.sum || displaySum;
- var arrays = {a: trace.a, b: trace.b, c: trace.c};
-
- var i, j, dataArray, newArray, fillArray1, fillArray2;
-
- // fill in one missing component
- for(i = 0; i < dataArrays.length; i++) {
- dataArray = dataArrays[i];
- if(arrays[dataArray]) continue;
-
- fillArray1 = arrays[arraysToFill[dataArray][0]];
- fillArray2 = arrays[arraysToFill[dataArray][1]];
- newArray = new Array(fillArray1.length);
- for(j = 0; j < fillArray1.length; j++) {
- newArray[j] = normSum - fillArray1[j] - fillArray2[j];
- }
- arrays[dataArray] = newArray;
- }
-
- // make the calcdata array
- var serieslen = trace._length;
- var cd = new Array(serieslen);
- var a, b, c, norm, x, y;
- for(i = 0; i < serieslen; i++) {
- a = arrays.a[i];
- b = arrays.b[i];
- c = arrays.c[i];
- if(isNumeric(a) && isNumeric(b) && isNumeric(c)) {
- a = +a;
- b = +b;
- c = +c;
- norm = displaySum / (a + b + c);
- if(norm !== 1) {
- a *= norm;
- b *= norm;
- c *= norm;
- }
- // map a, b, c onto x and y where the full scale of y
- // is [0, sum], and x is [-sum, sum]
- // TODO: this makes `a` always the top, `b` the bottom left,
- // and `c` the bottom right. Do we want options to rearrange
- // these?
- y = a;
- x = c - b;
- cd[i] = {x: x, y: y, a: a, b: b, c: c};
- } else cd[i] = {x: false, y: false};
- }
-
- calcMarkerSize(trace, serieslen);
- calcColorscale(gd, trace);
- arraysToCalcdata(cd, trace);
- calcSelection(cd, trace);
-
- return cd;
-};
-
-},{"../scatter/arrays_to_calcdata":364,"../scatter/calc":366,"../scatter/calc_selection":367,"../scatter/colorscale_calc":368,"fast-isnumeric":18}],393:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-var constants = _dereq_('../scatter/constants');
-var subTypes = _dereq_('../scatter/subtypes');
-var handleMarkerDefaults = _dereq_('../scatter/marker_defaults');
-var handleLineDefaults = _dereq_('../scatter/line_defaults');
-var handleLineShapeDefaults = _dereq_('../scatter/line_shape_defaults');
-var handleTextDefaults = _dereq_('../scatter/text_defaults');
-var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults');
-
-var attributes = _dereq_('./attributes');
-
-
-module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
- function coerce(attr, dflt) {
- return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
- }
-
- var a = coerce('a');
- var b = coerce('b');
- var c = coerce('c');
- var len;
-
- // allow any one array to be missing, len is the minimum length of those
- // present. Note that after coerce data_array's are either Arrays (which
- // are truthy even if empty) or undefined. As in scatter, an empty array
- // is different from undefined, because it can signify that this data is
- // not known yet but expected in the future
- if(a) {
- len = a.length;
- if(b) {
- len = Math.min(len, b.length);
- if(c) len = Math.min(len, c.length);
- } else if(c) len = Math.min(len, c.length);
- else len = 0;
- } else if(b && c) {
- len = Math.min(b.length, c.length);
- }
-
- if(!len) {
- traceOut.visible = false;
- return;
- }
-
- traceOut._length = len;
-
- coerce('sum');
-
- coerce('text');
- coerce('hovertext');
- if(traceOut.hoveron !== 'fills') coerce('hovertemplate');
-
- var defaultMode = len < constants.PTS_LINESONLY ? 'lines+markers' : 'lines';
- coerce('mode', defaultMode);
-
- if(subTypes.hasLines(traceOut)) {
- handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
- handleLineShapeDefaults(traceIn, traceOut, coerce);
- coerce('connectgaps');
- }
-
- if(subTypes.hasMarkers(traceOut)) {
- handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true});
- }
-
- if(subTypes.hasText(traceOut)) {
- handleTextDefaults(traceIn, traceOut, layout, coerce);
- }
-
- var dfltHoverOn = [];
-
- if(subTypes.hasMarkers(traceOut) || subTypes.hasText(traceOut)) {
- coerce('cliponaxis');
- coerce('marker.maxdisplayed');
- dfltHoverOn.push('points');
- }
-
- coerce('fill');
- if(traceOut.fill !== 'none') {
- handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce);
- if(!subTypes.hasLines(traceOut)) handleLineShapeDefaults(traceIn, traceOut, coerce);
- }
-
- if(traceOut.fill === 'tonext' || traceOut.fill === 'toself') {
- dfltHoverOn.push('fills');
- }
- coerce('hoveron', dfltHoverOn.join('+') || 'points');
-
- Lib.coerceSelectionMarkerOpacity(traceOut, coerce);
-};
-
-},{"../../lib":168,"../scatter/constants":369,"../scatter/fillcolor_defaults":373,"../scatter/line_defaults":377,"../scatter/line_shape_defaults":379,"../scatter/marker_defaults":383,"../scatter/subtypes":388,"../scatter/text_defaults":389,"./attributes":391}],394:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = function eventData(out, pt, trace, cd, pointNumber) {
- if(pt.xa) out.xaxis = pt.xa;
- if(pt.ya) out.yaxis = pt.ya;
-
- if(cd[pointNumber]) {
- var cdi = cd[pointNumber];
-
- // N.B. These are the normalized coordinates.
- out.a = cdi.a;
- out.b = cdi.b;
- out.c = cdi.c;
- } else {
- // for fill-hover only
- out.a = pt.a;
- out.b = pt.b;
- out.c = pt.c;
- }
-
- return out;
-};
-
-},{}],395:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var scatterHover = _dereq_('../scatter/hover');
-var Axes = _dereq_('../../plots/cartesian/axes');
-
-
-module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
- var scatterPointData = scatterHover(pointData, xval, yval, hovermode);
- if(!scatterPointData || scatterPointData[0].index === false) return;
-
- var newPointData = scatterPointData[0];
-
- // if hovering on a fill, we don't show any point data so the label is
- // unchanged from what scatter gives us - except that it needs to
- // be constrained to the trianglular plot area, not just the rectangular
- // area defined by the synthetic x and y axes
- // TODO: in some cases the vertical middle of the shape is not within
- // the triangular viewport at all, so the label can become disconnected
- // from the shape entirely. But calculating what portion of the shape
- // is actually visible, as constrained by the diagonal axis lines, is not
- // so easy and anyway we lost the information we would have needed to do
- // this inside scatterHover.
- if(newPointData.index === undefined) {
- var yFracUp = 1 - (newPointData.y0 / pointData.ya._length);
- var xLen = pointData.xa._length;
- var xMin = xLen * yFracUp / 2;
- var xMax = xLen - xMin;
- newPointData.x0 = Math.max(Math.min(newPointData.x0, xMax), xMin);
- newPointData.x1 = Math.max(Math.min(newPointData.x1, xMax), xMin);
- return scatterPointData;
- }
-
- var cdi = newPointData.cd[newPointData.index];
-
- newPointData.a = cdi.a;
- newPointData.b = cdi.b;
- newPointData.c = cdi.c;
-
- newPointData.xLabelVal = undefined;
- newPointData.yLabelVal = undefined;
- // TODO: nice formatting, and label by axis title, for a, b, and c?
-
- var trace = newPointData.trace;
- var ternary = newPointData.subplot;
- var hoverinfo = cdi.hi || trace.hoverinfo;
- var text = [];
- function textPart(ax, val) {
- text.push(ax._hovertitle + ': ' + Axes.tickText(ax, val, 'hover').text);
- }
- if(!trace.hovertemplate) {
- var parts = hoverinfo.split('+');
- if(parts.indexOf('all') !== -1) parts = ['a', 'b', 'c'];
- if(parts.indexOf('a') !== -1) textPart(ternary.aaxis, cdi.a);
- if(parts.indexOf('b') !== -1) textPart(ternary.baxis, cdi.b);
- if(parts.indexOf('c') !== -1) textPart(ternary.caxis, cdi.c);
- }
- newPointData.extraText = text.join('
');
- newPointData.hovertemplate = trace.hovertemplate;
- return scatterPointData;
-};
-
-},{"../../plots/cartesian/axes":212,"../scatter/hover":375}],396:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = {
- attributes: _dereq_('./attributes'),
- supplyDefaults: _dereq_('./defaults'),
- colorbar: _dereq_('../scatter/marker_colorbar'),
- calc: _dereq_('./calc'),
- plot: _dereq_('./plot'),
- style: _dereq_('../scatter/style').style,
- styleOnSelect: _dereq_('../scatter/style').styleOnSelect,
- hoverPoints: _dereq_('./hover'),
- selectPoints: _dereq_('../scatter/select'),
- eventData: _dereq_('./event_data'),
-
- moduleType: 'trace',
- name: 'scatterternary',
- basePlotModule: _dereq_('../../plots/ternary'),
- categories: ['ternary', 'symbols', 'showLegend', 'scatter-like'],
- meta: {
-
-
- }
-};
-
-},{"../../plots/ternary":252,"../scatter/marker_colorbar":382,"../scatter/select":385,"../scatter/style":387,"./attributes":391,"./calc":392,"./defaults":393,"./event_data":394,"./hover":395,"./plot":397}],397:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-
-'use strict';
-
-var scatterPlot = _dereq_('../scatter/plot');
-
-module.exports = function plot(gd, ternary, moduleCalcData) {
- var plotContainer = ternary.plotContainer;
-
- // remove all nodes inside the scatter layer
- plotContainer.select('.scatterlayer').selectAll('*').remove();
-
- // mimic cartesian plotinfo
- var plotinfo = {
- xaxis: ternary.xaxis,
- yaxis: ternary.yaxis,
- plot: plotContainer,
- layerClipId: ternary._hasClipOnAxisFalse ? ternary.clipIdRelative : null
- };
-
- var scatterLayer = ternary.layers.frontplot.select('g.scatterlayer');
-
- scatterPlot(gd, plotinfo, moduleCalcData, scatterLayer);
-};
-
-},{"../scatter/plot":384}],398:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var boxAttrs = _dereq_('../box/attributes');
-var extendFlat = _dereq_('../../lib/extend').extendFlat;
-
-module.exports = {
- y: boxAttrs.y,
- x: boxAttrs.x,
- x0: boxAttrs.x0,
- y0: boxAttrs.y0,
- name: extendFlat({}, boxAttrs.name, {
-
- }),
- orientation: extendFlat({}, boxAttrs.orientation, {
-
- }),
-
- bandwidth: {
- valType: 'number',
- min: 0,
-
- editType: 'calc',
-
- },
-
- scalegroup: {
- valType: 'string',
-
- dflt: '',
- editType: 'calc',
-
- },
- scalemode: {
- valType: 'enumerated',
- values: ['width', 'count'],
- dflt: 'width',
-
- editType: 'calc',
-
- },
-
- spanmode: {
- valType: 'enumerated',
- values: ['soft', 'hard', 'manual'],
- dflt: 'soft',
-
- editType: 'calc',
-
- },
- span: {
- valType: 'info_array',
- items: [
- {valType: 'any', editType: 'calc'},
- {valType: 'any', editType: 'calc'}
- ],
-
- editType: 'calc',
-
- },
-
- line: {
- color: {
- valType: 'color',
-
- editType: 'style',
-
- },
- width: {
- valType: 'number',
-
- min: 0,
- dflt: 2,
- editType: 'style',
-
- },
- editType: 'plot'
- },
- fillcolor: boxAttrs.fillcolor,
-
- points: extendFlat({}, boxAttrs.boxpoints, {
-
- }),
- jitter: extendFlat({}, boxAttrs.jitter, {
-
- }),
- pointpos: extendFlat({}, boxAttrs.pointpos, {
-
- }),
-
- width: extendFlat({}, boxAttrs.width, {
-
- }),
-
- marker: boxAttrs.marker,
- text: boxAttrs.text,
- hovertext: boxAttrs.hovertext,
- hovertemplate: boxAttrs.hovertemplate,
-
- box: {
- visible: {
- valType: 'boolean',
- dflt: false,
-
- editType: 'plot',
-
- },
- width: {
- valType: 'number',
- min: 0,
- max: 1,
- dflt: 0.25,
-
- editType: 'plot',
-
- },
- fillcolor: {
- valType: 'color',
-
- editType: 'style',
-
- },
- line: {
- color: {
- valType: 'color',
-
- editType: 'style',
-
- },
- width: {
- valType: 'number',
- min: 0,
-
- editType: 'style',
-
- },
- editType: 'style'
- },
- editType: 'plot'
- },
-
- meanline: {
- visible: {
- valType: 'boolean',
- dflt: false,
-
- editType: 'plot',
-
- },
- color: {
- valType: 'color',
-
- editType: 'style',
-
- },
- width: {
- valType: 'number',
- min: 0,
-
- editType: 'style',
-
- },
- editType: 'plot'
- },
-
- side: {
- valType: 'enumerated',
- values: ['both', 'positive', 'negative'],
- dflt: 'both',
-
- editType: 'calc',
-
- },
-
- offsetgroup: boxAttrs.offsetgroup,
- alignmentgroup: boxAttrs.alignmentgroup,
-
- selected: boxAttrs.selected,
- unselected: boxAttrs.unselected,
-
- hoveron: {
- valType: 'flaglist',
- flags: ['violins', 'points', 'kde'],
- dflt: 'violins+points+kde',
- extras: ['all'],
-
- editType: 'style',
-
- }
-};
-
-},{"../../lib/extend":162,"../box/attributes":281}],399:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var Axes = _dereq_('../../plots/cartesian/axes');
-var boxCalc = _dereq_('../box/calc');
-var helpers = _dereq_('./helpers');
-var BADNUM = _dereq_('../../constants/numerical').BADNUM;
-
-module.exports = function calc(gd, trace) {
- var cd = boxCalc(gd, trace);
-
- if(cd[0].t.empty) return cd;
-
- var fullLayout = gd._fullLayout;
- var valAxis = Axes.getFromId(
- gd,
- trace[trace.orientation === 'h' ? 'xaxis' : 'yaxis']
- );
-
- var spanMin = Infinity;
- var spanMax = -Infinity;
- var maxKDE = 0;
- var maxCount = 0;
-
- for(var i = 0; i < cd.length; i++) {
- var cdi = cd[i];
- var vals = cdi.pts.map(helpers.extractVal);
-
- var bandwidth = cdi.bandwidth = calcBandwidth(trace, cdi, vals);
- var span = cdi.span = calcSpan(trace, cdi, valAxis, bandwidth);
-
- if(cdi.min === cdi.max && bandwidth === 0) {
- // if span is zero and bandwidth is zero, we want a violin with zero width
- span = cdi.span = [cdi.min, cdi.max];
- cdi.density = [{v: 1, t: span[0]}];
- cdi.bandwidth = bandwidth;
- maxKDE = Math.max(maxKDE, 1);
- } else {
- // step that well covers the bandwidth and is multiple of span distance
- var dist = span[1] - span[0];
- var n = Math.ceil(dist / (bandwidth / 3));
- var step = dist / n;
-
- if(!isFinite(step) || !isFinite(n)) {
- Lib.error('Something went wrong with computing the violin span');
- cd[0].t.empty = true;
- return cd;
- }
-
- var kde = helpers.makeKDE(cdi, trace, vals);
- cdi.density = new Array(n);
-
- for(var k = 0, t = span[0]; t < (span[1] + step / 2); k++, t += step) {
- var v = kde(t);
- cdi.density[k] = {v: v, t: t};
- maxKDE = Math.max(maxKDE, v);
- }
- }
-
- maxCount = Math.max(maxCount, vals.length);
- spanMin = Math.min(spanMin, span[0]);
- spanMax = Math.max(spanMax, span[1]);
- }
-
- var extremes = Axes.findExtremes(valAxis, [spanMin, spanMax], {padded: true});
- trace._extremes[valAxis._id] = extremes;
-
- if(trace.width) {
- cd[0].t.maxKDE = maxKDE;
- } else {
- var violinScaleGroupStats = fullLayout._violinScaleGroupStats;
- var scaleGroup = trace.scalegroup;
- var groupStats = violinScaleGroupStats[scaleGroup];
-
- if(groupStats) {
- groupStats.maxKDE = Math.max(groupStats.maxKDE, maxKDE);
- groupStats.maxCount = Math.max(groupStats.maxCount, maxCount);
- } else {
- violinScaleGroupStats[scaleGroup] = {
- maxKDE: maxKDE,
- maxCount: maxCount
- };
- }
- }
-
- cd[0].t.labels.kde = Lib._(gd, 'kde:');
-
- return cd;
-};
-
-// Default to Silveman's rule of thumb
-// - https://stats.stackexchange.com/a/6671
-// - https://en.wikipedia.org/wiki/Kernel_density_estimation#A_rule-of-thumb_bandwidth_estimator
-// - https://github.com/statsmodels/statsmodels/blob/master/statsmodels/nonparametric/bandwidths.py
-function silvermanRule(len, ssd, iqr) {
- var a = Math.min(ssd, iqr / 1.349);
- return 1.059 * a * Math.pow(len, -0.2);
-}
-
-function calcBandwidth(trace, cdi, vals) {
- var span = cdi.max - cdi.min;
-
- // If span is zero
- if(!span) {
- if(trace.bandwidth) {
- return trace.bandwidth;
- } else {
- // if span is zero and no bandwidth is specified
- // it returns zero bandwidth which is a special case
- return 0;
- }
- }
-
- // Limit how small the bandwidth can be.
- //
- // Silverman's rule of thumb can be "very" small
- // when IQR does a poor job at describing the spread
- // of the distribution.
- // We also want to limit custom bandwidths
- // to not blow up kde computations.
-
- if(trace.bandwidth) {
- return Math.max(trace.bandwidth, span / 1e4);
- } else {
- var len = vals.length;
- var ssd = Lib.stdev(vals, len - 1, cdi.mean);
- return Math.max(
- silvermanRule(len, ssd, cdi.q3 - cdi.q1),
- span / 100
- );
- }
-}
-
-function calcSpan(trace, cdi, valAxis, bandwidth) {
- var spanmode = trace.spanmode;
- var spanIn = trace.span || [];
- var spanTight = [cdi.min, cdi.max];
- var spanLoose = [cdi.min - 2 * bandwidth, cdi.max + 2 * bandwidth];
- var spanOut;
-
- function calcSpanItem(index) {
- var s = spanIn[index];
- var sc = valAxis.type === 'multicategory' ?
- valAxis.r2c(s) :
- valAxis.d2c(s, 0, trace[cdi.valLetter + 'calendar']);
- return sc === BADNUM ? spanLoose[index] : sc;
- }
-
- if(spanmode === 'soft') {
- spanOut = spanLoose;
- } else if(spanmode === 'hard') {
- spanOut = spanTight;
- } else {
- spanOut = [calcSpanItem(0), calcSpanItem(1)];
- }
-
- // to reuse the equal-range-item block
- var dummyAx = {
- type: 'linear',
- range: spanOut
- };
- Axes.setConvert(dummyAx);
- dummyAx.cleanRange();
-
- return spanOut;
-}
-
-},{"../../constants/numerical":149,"../../lib":168,"../../plots/cartesian/axes":212,"../box/calc":282,"./helpers":402}],400:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var setPositionOffset = _dereq_('../box/cross_trace_calc').setPositionOffset;
-var orientations = ['v', 'h'];
-
-module.exports = function crossTraceCalc(gd, plotinfo) {
- var calcdata = gd.calcdata;
- var xa = plotinfo.xaxis;
- var ya = plotinfo.yaxis;
-
- for(var i = 0; i < orientations.length; i++) {
- var orientation = orientations[i];
- var posAxis = orientation === 'h' ? ya : xa;
- var violinList = [];
-
- for(var j = 0; j < calcdata.length; j++) {
- var cd = calcdata[j];
- var t = cd[0].t;
- var trace = cd[0].trace;
-
- if(trace.visible === true && trace.type === 'violin' &&
- !t.empty &&
- trace.orientation === orientation &&
- trace.xaxis === xa._id &&
- trace.yaxis === ya._id
- ) {
- violinList.push(j);
- }
- }
-
- setPositionOffset('violin', gd, violinList, posAxis);
- }
-};
-
-},{"../box/cross_trace_calc":283}],401:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var Color = _dereq_('../../components/color');
-
-var boxDefaults = _dereq_('../box/defaults');
-var attributes = _dereq_('./attributes');
-
-module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
- function coerce(attr, dflt) {
- return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
- }
- function coerce2(attr, dflt) {
- return Lib.coerce2(traceIn, traceOut, attributes, attr, dflt);
- }
-
- boxDefaults.handleSampleDefaults(traceIn, traceOut, coerce, layout);
- if(traceOut.visible === false) return;
-
- coerce('bandwidth');
- coerce('side');
-
- var width = coerce('width');
- if(!width) {
- coerce('scalegroup', traceOut.name);
- coerce('scalemode');
- }
-
- var span = coerce('span');
- var spanmodeDflt;
- if(Array.isArray(span)) spanmodeDflt = 'manual';
- coerce('spanmode', spanmodeDflt);
-
- var lineColor = coerce('line.color', (traceIn.marker || {}).color || defaultColor);
- var lineWidth = coerce('line.width');
- var fillColor = coerce('fillcolor', Color.addOpacity(traceOut.line.color, 0.5));
-
- boxDefaults.handlePointsDefaults(traceIn, traceOut, coerce, {prefix: ''});
-
- var boxWidth = coerce2('box.width');
- var boxFillColor = coerce2('box.fillcolor', fillColor);
- var boxLineColor = coerce2('box.line.color', lineColor);
- var boxLineWidth = coerce2('box.line.width', lineWidth);
- var boxVisible = coerce('box.visible', Boolean(boxWidth || boxFillColor || boxLineColor || boxLineWidth));
- if(!boxVisible) traceOut.box = {visible: false};
-
- var meanLineColor = coerce2('meanline.color', lineColor);
- var meanLineWidth = coerce2('meanline.width', lineWidth);
- var meanLineVisible = coerce('meanline.visible', Boolean(meanLineColor || meanLineWidth));
- if(!meanLineVisible) traceOut.meanline = {visible: false};
-};
-
-},{"../../components/color":51,"../../lib":168,"../box/defaults":284,"./attributes":398}],402:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-
-// Maybe add kernels more down the road,
-// but note that the default `spanmode: 'soft'` bounds might have
-// to become kernel-dependent
-var kernels = {
- gaussian: function(v) {
- return (1 / Math.sqrt(2 * Math.PI)) * Math.exp(-0.5 * v * v);
- }
-};
-
-exports.makeKDE = function(calcItem, trace, vals) {
- var len = vals.length;
- var kernel = kernels.gaussian;
- var bandwidth = calcItem.bandwidth;
- var factor = 1 / (len * bandwidth);
-
- // don't use Lib.aggNums to skip isNumeric checks
- return function(x) {
- var sum = 0;
- for(var i = 0; i < len; i++) {
- sum += kernel((x - vals[i]) / bandwidth);
- }
- return factor * sum;
- };
-};
-
-exports.getPositionOnKdePath = function(calcItem, trace, valuePx) {
- var posLetter, valLetter;
-
- if(trace.orientation === 'h') {
- posLetter = 'y';
- valLetter = 'x';
- } else {
- posLetter = 'x';
- valLetter = 'y';
- }
-
- var pointOnPath = Lib.findPointOnPath(
- calcItem.path,
- valuePx,
- valLetter,
- {pathLength: calcItem.pathLength}
- );
-
- var posCenterPx = calcItem.posCenterPx;
- var posOnPath0 = pointOnPath[posLetter];
- var posOnPath1 = trace.side === 'both' ?
- 2 * posCenterPx - posOnPath0 :
- posCenterPx;
-
- return [posOnPath0, posOnPath1];
-};
-
-exports.getKdeValue = function(calcItem, trace, valueDist) {
- var vals = calcItem.pts.map(exports.extractVal);
- var kde = exports.makeKDE(calcItem, trace, vals);
- return kde(valueDist) / calcItem.posDensityScale;
-};
-
-exports.extractVal = function(o) { return o.v; };
-
-},{"../../lib":168}],403:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var Axes = _dereq_('../../plots/cartesian/axes');
-var boxHoverPoints = _dereq_('../box/hover');
-var helpers = _dereq_('./helpers');
-
-module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLayer) {
- var cd = pointData.cd;
- var trace = cd[0].trace;
- var hoveron = trace.hoveron;
- var hasHoveronViolins = hoveron.indexOf('violins') !== -1;
- var hasHoveronKDE = hoveron.indexOf('kde') !== -1;
- var closeData = [];
- var closePtData;
- var violinLineAttrs;
-
- if(hasHoveronViolins || hasHoveronKDE) {
- var closeBoxData = boxHoverPoints.hoverOnBoxes(pointData, xval, yval, hovermode);
-
- if(hasHoveronKDE && closeBoxData.length > 0) {
- var xa = pointData.xa;
- var ya = pointData.ya;
- var pLetter, vLetter, pAxis, vAxis, vVal;
-
- if(trace.orientation === 'h') {
- vVal = xval;
- pLetter = 'y';
- pAxis = ya;
- vLetter = 'x';
- vAxis = xa;
- } else {
- vVal = yval;
- pLetter = 'x';
- pAxis = xa;
- vLetter = 'y';
- vAxis = ya;
- }
-
- var di = cd[pointData.index];
-
- if(vVal >= di.span[0] && vVal <= di.span[1]) {
- var kdePointData = Lib.extendFlat({}, pointData);
- var vValPx = vAxis.c2p(vVal, true);
- var kdeVal = helpers.getKdeValue(di, trace, vVal);
- var pOnPath = helpers.getPositionOnKdePath(di, trace, vValPx);
- var paOffset = pAxis._offset;
- var paLength = pAxis._length;
-
- kdePointData[pLetter + '0'] = pOnPath[0];
- kdePointData[pLetter + '1'] = pOnPath[1];
- kdePointData[vLetter + '0'] = kdePointData[vLetter + '1'] = vValPx;
- kdePointData[vLetter + 'Label'] = vLetter + ': ' + Axes.hoverLabelText(vAxis, vVal) + ', ' + cd[0].t.labels.kde + ' ' + kdeVal.toFixed(3);
-
- // move the spike to the KDE point
- kdePointData.spikeDistance = closeBoxData[0].spikeDistance;
- var spikePosAttr = pLetter + 'Spike';
- kdePointData[spikePosAttr] = closeBoxData[0][spikePosAttr];
- closeBoxData[0].spikeDistance = undefined;
- closeBoxData[0][spikePosAttr] = undefined;
-
- // no hovertemplate support yet
- kdePointData.hovertemplate = false;
-
- closeData.push(kdePointData);
-
- violinLineAttrs = {stroke: pointData.color};
- violinLineAttrs[pLetter + '1'] = Lib.constrain(paOffset + pOnPath[0], paOffset, paOffset + paLength);
- violinLineAttrs[pLetter + '2'] = Lib.constrain(paOffset + pOnPath[1], paOffset, paOffset + paLength);
- violinLineAttrs[vLetter + '1'] = violinLineAttrs[vLetter + '2'] = vAxis._offset + vValPx;
- }
- }
-
- if(hasHoveronViolins) {
- closeData = closeData.concat(closeBoxData);
- }
- }
-
- if(hoveron.indexOf('points') !== -1) {
- closePtData = boxHoverPoints.hoverOnPoints(pointData, xval, yval);
- }
-
- // update violin line (if any)
- var violinLine = hoverLayer.selectAll('.violinline-' + trace.uid)
- .data(violinLineAttrs ? [0] : []);
- violinLine.enter().append('line')
- .classed('violinline-' + trace.uid, true)
- .attr('stroke-width', 1.5);
- violinLine.exit().remove();
- violinLine.attr(violinLineAttrs);
-
- // same combine logic as box hoverPoints
- if(hovermode === 'closest') {
- if(closePtData) return [closePtData];
- return closeData;
- }
- if(closePtData) {
- closeData.push(closePtData);
- return closeData;
- }
- return closeData;
-};
-
-},{"../../lib":168,"../../plots/cartesian/axes":212,"../box/hover":286,"./helpers":402}],404:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = {
- attributes: _dereq_('./attributes'),
- layoutAttributes: _dereq_('./layout_attributes'),
- supplyDefaults: _dereq_('./defaults'),
- crossTraceDefaults: _dereq_('../box/defaults').crossTraceDefaults,
- supplyLayoutDefaults: _dereq_('./layout_defaults'),
- calc: _dereq_('./calc'),
- crossTraceCalc: _dereq_('./cross_trace_calc'),
- plot: _dereq_('./plot'),
- style: _dereq_('./style'),
- styleOnSelect: _dereq_('../scatter/style').styleOnSelect,
- hoverPoints: _dereq_('./hover'),
- selectPoints: _dereq_('../box/select'),
-
- moduleType: 'trace',
- name: 'violin',
- basePlotModule: _dereq_('../../plots/cartesian'),
- categories: ['cartesian', 'svg', 'symbols', 'oriented', 'box-violin', 'showLegend', 'violinLayout', 'zoomScale'],
- meta: {
-
- }
-};
-
-},{"../../plots/cartesian":223,"../box/defaults":284,"../box/select":291,"../scatter/style":387,"./attributes":398,"./calc":399,"./cross_trace_calc":400,"./defaults":401,"./hover":403,"./layout_attributes":405,"./layout_defaults":406,"./plot":407,"./style":408}],405:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var boxLayoutAttrs = _dereq_('../box/layout_attributes');
-var extendFlat = _dereq_('../../lib').extendFlat;
-
-module.exports = {
- violinmode: extendFlat({}, boxLayoutAttrs.boxmode, {
-
- }),
- violingap: extendFlat({}, boxLayoutAttrs.boxgap, {
-
- }),
- violingroupgap: extendFlat({}, boxLayoutAttrs.boxgroupgap, {
-
- })
-};
-
-},{"../../lib":168,"../box/layout_attributes":288}],406:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var Lib = _dereq_('../../lib');
-var layoutAttributes = _dereq_('./layout_attributes');
-var boxLayoutDefaults = _dereq_('../box/layout_defaults');
-
-module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
- function coerce(attr, dflt) {
- return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt);
- }
- boxLayoutDefaults._supply(layoutIn, layoutOut, fullData, coerce, 'violin');
-};
-
-},{"../../lib":168,"../box/layout_defaults":289,"./layout_attributes":405}],407:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var d3 = _dereq_('d3');
-var Lib = _dereq_('../../lib');
-var Drawing = _dereq_('../../components/drawing');
-
-var boxPlot = _dereq_('../box/plot');
-var linePoints = _dereq_('../scatter/line_points');
-var helpers = _dereq_('./helpers');
-
-module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) {
- var fullLayout = gd._fullLayout;
- var xa = plotinfo.xaxis;
- var ya = plotinfo.yaxis;
-
- function makePath(pts) {
- var segments = linePoints(pts, {
- xaxis: xa,
- yaxis: ya,
- connectGaps: true,
- baseTolerance: 0.75,
- shape: 'spline',
- simplify: true
- });
- return Drawing.smoothopen(segments[0], 1);
- }
-
- Lib.makeTraceGroups(violinLayer, cdViolins, 'trace violins').each(function(cd) {
- var plotGroup = d3.select(this);
- var cd0 = cd[0];
- var t = cd0.t;
- var trace = cd0.trace;
- if(!plotinfo.isRangePlot) cd0.node3 = plotGroup;
-
- if(trace.visible !== true || t.empty) {
- plotGroup.remove();
- return;
- }
-
- var bPos = t.bPos;
- var bdPos = t.bdPos;
- var valAxis = plotinfo[t.valLetter + 'axis'];
- var posAxis = plotinfo[t.posLetter + 'axis'];
- var hasBothSides = trace.side === 'both';
- var hasPositiveSide = hasBothSides || trace.side === 'positive';
- var hasNegativeSide = hasBothSides || trace.side === 'negative';
-
- var violins = plotGroup.selectAll('path.violin').data(Lib.identity);
-
- violins.enter().append('path')
- .style('vector-effect', 'non-scaling-stroke')
- .attr('class', 'violin');
-
- violins.exit().remove();
-
- violins.each(function(d) {
- var pathSel = d3.select(this);
- var density = d.density;
- var len = density.length;
- var posCenter = d.pos + bPos;
- var posCenterPx = posAxis.c2p(posCenter);
-
- var scale;
- if(trace.width) {
- scale = t.maxKDE / bdPos;
- } else {
- var groupStats = fullLayout._violinScaleGroupStats[trace.scalegroup];
- scale = trace.scalemode === 'count' ?
- (groupStats.maxKDE / bdPos) * (groupStats.maxCount / d.pts.length) :
- groupStats.maxKDE / bdPos;
- }
-
- var pathPos, pathNeg, path;
- var i, k, pts, pt;
-
- if(hasPositiveSide) {
- pts = new Array(len);
- for(i = 0; i < len; i++) {
- pt = pts[i] = {};
- pt[t.posLetter] = posCenter + (density[i].v / scale);
- pt[t.valLetter] = density[i].t;
- }
- pathPos = makePath(pts);
- }
-
- if(hasNegativeSide) {
- pts = new Array(len);
- for(k = 0, i = len - 1; k < len; k++, i--) {
- pt = pts[k] = {};
- pt[t.posLetter] = posCenter - (density[i].v / scale);
- pt[t.valLetter] = density[i].t;
- }
- pathNeg = makePath(pts);
- }
-
- if(hasBothSides) {
- path = pathPos + 'L' + pathNeg.substr(1) + 'Z';
- } else {
- var startPt = [posCenterPx, valAxis.c2p(density[0].t)];
- var endPt = [posCenterPx, valAxis.c2p(density[len - 1].t)];
-
- if(trace.orientation === 'h') {
- startPt.reverse();
- endPt.reverse();
- }
-
- if(hasPositiveSide) {
- path = 'M' + startPt + 'L' + pathPos.substr(1) + 'L' + endPt;
- } else {
- path = 'M' + endPt + 'L' + pathNeg.substr(1) + 'L' + startPt;
- }
- }
- pathSel.attr('d', path);
-
- // save a few things used in getPositionOnKdePath, getKdeValue
- // on hover and for meanline draw block below
- d.posCenterPx = posCenterPx;
- d.posDensityScale = scale * bdPos;
- d.path = pathSel.node();
- d.pathLength = d.path.getTotalLength() / (hasBothSides ? 2 : 1);
- });
-
- var boxAttrs = trace.box;
- var boxWidth = boxAttrs.width;
- var boxLineWidth = (boxAttrs.line || {}).width;
- var bdPosScaled;
- var bPosPxOffset;
-
- if(hasBothSides) {
- bdPosScaled = bdPos * boxWidth;
- bPosPxOffset = 0;
- } else if(hasPositiveSide) {
- bdPosScaled = [0, bdPos * boxWidth / 2];
- bPosPxOffset = -boxLineWidth;
- } else {
- bdPosScaled = [bdPos * boxWidth / 2, 0];
- bPosPxOffset = boxLineWidth;
- }
-
- // inner box
- boxPlot.plotBoxAndWhiskers(plotGroup, {pos: posAxis, val: valAxis}, trace, {
- bPos: bPos,
- bdPos: bdPosScaled,
- bPosPxOffset: bPosPxOffset
- });
-
- // meanline insider box
- boxPlot.plotBoxMean(plotGroup, {pos: posAxis, val: valAxis}, trace, {
- bPos: bPos,
- bdPos: bdPosScaled,
- bPosPxOffset: bPosPxOffset
- });
-
- var fn;
- if(!trace.box.visible && trace.meanline.visible) {
- fn = Lib.identity;
- }
-
- // N.B. use different class name than boxPlot.plotBoxMean,
- // to avoid selectAll conflict
- var meanPaths = plotGroup.selectAll('path.meanline').data(fn || []);
- meanPaths.enter().append('path')
- .attr('class', 'meanline')
- .style('fill', 'none')
- .style('vector-effect', 'non-scaling-stroke');
- meanPaths.exit().remove();
- meanPaths.each(function(d) {
- var v = valAxis.c2p(d.mean, true);
- var p = helpers.getPositionOnKdePath(d, trace, v);
-
- d3.select(this).attr('d',
- trace.orientation === 'h' ?
- 'M' + v + ',' + p[0] + 'V' + p[1] :
- 'M' + p[0] + ',' + v + 'H' + p[1]
- );
- });
-
- boxPlot.plotPoints(plotGroup, {x: xa, y: ya}, trace, t);
- });
-};
-
-},{"../../components/drawing":72,"../../lib":168,"../box/plot":290,"../scatter/line_points":378,"./helpers":402,"d3":16}],408:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-var d3 = _dereq_('d3');
-var Color = _dereq_('../../components/color');
-var stylePoints = _dereq_('../scatter/style').stylePoints;
-
-module.exports = function style(gd, cd) {
- var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.violins');
-
- s.style('opacity', function(d) { return d[0].trace.opacity; });
-
- s.each(function(d) {
- var trace = d[0].trace;
- var sel = d3.select(this);
- var box = trace.box || {};
- var boxLine = box.line || {};
- var meanline = trace.meanline || {};
- var meanLineWidth = meanline.width;
-
- sel.selectAll('path.violin')
- .style('stroke-width', trace.line.width + 'px')
- .call(Color.stroke, trace.line.color)
- .call(Color.fill, trace.fillcolor);
-
- sel.selectAll('path.box')
- .style('stroke-width', boxLine.width + 'px')
- .call(Color.stroke, boxLine.color)
- .call(Color.fill, box.fillcolor);
-
- var meanLineStyle = {
- 'stroke-width': meanLineWidth + 'px',
- 'stroke-dasharray': (2 * meanLineWidth) + 'px,' + meanLineWidth + 'px'
- };
-
- sel.selectAll('path.mean')
- .style(meanLineStyle)
- .call(Color.stroke, meanline.color);
-
- sel.selectAll('path.meanline')
- .style(meanLineStyle)
- .call(Color.stroke, meanline.color);
-
- stylePoints(sel, trace, gd);
- });
-};
-
-},{"../../components/color":51,"../scatter/style":387,"d3":16}]},{},[11])(11)
-});
diff --git a/static/babybuddy/js/graph.da32e0532ca2.js.gz b/static/babybuddy/js/graph.da32e0532ca2.js.gz
deleted file mode 100644
index f7fa75b6..00000000
Binary files a/static/babybuddy/js/graph.da32e0532ca2.js.gz and /dev/null differ
diff --git a/static/babybuddy/js/graph.js b/static/babybuddy/js/graph.js
index e0637637..7cb2d646 100644
--- a/static/babybuddy/js/graph.js
+++ b/static/babybuddy/js/graph.js
@@ -1,5 +1,5 @@
/**
-* plotly.js (cartesian) v1.48.2
+* plotly.js (cartesian) v1.51.3
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
* Licensed under the MIT license
@@ -72,137 +72,7 @@ for(var selector in rules) {
Lib.addStyleRule(fullSelector, rules[selector]);
}
-},{"../src/lib":168}],2:[function(_dereq_,module,exports){
-'use strict';
-
-module.exports = {
- 'undo': {
- 'width': 857.1,
- 'height': 1000,
- 'path': 'm857 350q0-87-34-166t-91-137-137-92-166-34q-96 0-183 41t-147 114q-4 6-4 13t5 11l76 77q6 5 14 5 9-1 13-7 41-53 100-82t126-29q58 0 110 23t92 61 61 91 22 111-22 111-61 91-92 61-110 23q-55 0-105-20t-90-57l77-77q17-16 8-38-10-23-33-23h-250q-15 0-25 11t-11 25v250q0 24 22 33 22 10 39-8l72-72q60 57 137 88t159 31q87 0 166-34t137-92 91-137 34-166z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'home': {
- 'width': 928.6,
- 'height': 1000,
- 'path': 'm786 296v-267q0-15-11-26t-25-10h-214v214h-143v-214h-214q-15 0-25 10t-11 26v267q0 1 0 2t0 2l321 264 321-264q1-1 1-4z m124 39l-34-41q-5-5-12-6h-2q-7 0-12 3l-386 322-386-322q-7-4-13-4-7 2-12 7l-35 41q-4 5-3 13t6 12l401 334q18 15 42 15t43-15l136-114v109q0 8 5 13t13 5h107q8 0 13-5t5-13v-227l122-102q5-5 6-12t-4-13z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'camera-retro': {
- 'width': 1000,
- 'height': 1000,
- 'path': 'm518 386q0 8-5 13t-13 5q-37 0-63-27t-26-63q0-8 5-13t13-5 12 5 5 13q0 23 16 38t38 16q8 0 13 5t5 13z m125-73q0-59-42-101t-101-42-101 42-42 101 42 101 101 42 101-42 42-101z m-572-320h858v71h-858v-71z m643 320q0 89-62 152t-152 62-151-62-63-152 63-151 151-63 152 63 62 151z m-571 358h214v72h-214v-72z m-72-107h858v143h-462l-36-71h-360v-72z m929 143v-714q0-30-21-51t-50-21h-858q-29 0-50 21t-21 51v714q0 30 21 51t50 21h858q29 0 50-21t21-51z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'zoombox': {
- 'width': 1000,
- 'height': 1000,
- 'path': 'm1000-25l-250 251c40 63 63 138 63 218 0 224-182 406-407 406-224 0-406-182-406-406s183-406 407-406c80 0 155 22 218 62l250-250 125 125z m-812 250l0 438 437 0 0-438-437 0z m62 375l313 0 0-312-313 0 0 312z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'pan': {
- 'width': 1000,
- 'height': 1000,
- 'path': 'm1000 350l-187 188 0-125-250 0 0 250 125 0-188 187-187-187 125 0 0-250-250 0 0 125-188-188 186-187 0 125 252 0 0-250-125 0 187-188 188 188-125 0 0 250 250 0 0-126 187 188z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'zoom_plus': {
- 'width': 875,
- 'height': 1000,
- 'path': 'm1 787l0-875 875 0 0 875-875 0z m687-500l-187 0 0-187-125 0 0 187-188 0 0 125 188 0 0 187 125 0 0-187 187 0 0-125z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'zoom_minus': {
- 'width': 875,
- 'height': 1000,
- 'path': 'm0 788l0-876 875 0 0 876-875 0z m688-500l-500 0 0 125 500 0 0-125z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'autoscale': {
- 'width': 1000,
- 'height': 1000,
- 'path': 'm250 850l-187 0-63 0 0-62 0-188 63 0 0 188 187 0 0 62z m688 0l-188 0 0-62 188 0 0-188 62 0 0 188 0 62-62 0z m-875-938l0 188-63 0 0-188 0-62 63 0 187 0 0 62-187 0z m875 188l0-188-188 0 0-62 188 0 62 0 0 62 0 188-62 0z m-125 188l-1 0-93-94-156 156 156 156 92-93 2 0 0 250-250 0 0-2 93-92-156-156-156 156 94 92 0 2-250 0 0-250 0 0 93 93 157-156-157-156-93 94 0 0 0-250 250 0 0 0-94 93 156 157 156-157-93-93 0 0 250 0 0 250z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'tooltip_basic': {
- 'width': 1500,
- 'height': 1000,
- 'path': 'm375 725l0 0-375-375 375-374 0-1 1125 0 0 750-1125 0z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'tooltip_compare': {
- 'width': 1125,
- 'height': 1000,
- 'path': 'm187 786l0 2-187-188 188-187 0 0 937 0 0 373-938 0z m0-499l0 1-187-188 188-188 0 0 937 0 0 376-938-1z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'plotlylogo': {
- 'width': 1542,
- 'height': 1000,
- 'path': 'm0-10h182v-140h-182v140z m228 146h183v-286h-183v286z m225 714h182v-1000h-182v1000z m225-285h182v-715h-182v715z m225 142h183v-857h-183v857z m231-428h182v-429h-182v429z m225-291h183v-138h-183v138z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'z-axis': {
- 'width': 1000,
- 'height': 1000,
- 'path': 'm833 5l-17 108v41l-130-65 130-66c0 0 0 38 0 39 0-1 36-14 39-25 4-15-6-22-16-30-15-12-39-16-56-20-90-22-187-23-279-23-261 0-341 34-353 59 3 60 228 110 228 110-140-8-351-35-351-116 0-120 293-142 474-142 155 0 477 22 477 142 0 50-74 79-163 96z m-374 94c-58-5-99-21-99-40 0-24 65-43 144-43 79 0 143 19 143 43 0 19-42 34-98 40v216h87l-132 135-133-135h88v-216z m167 515h-136v1c16 16 31 34 46 52l84 109v54h-230v-71h124v-1c-16-17-28-32-44-51l-89-114v-51h245v72z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- '3d_rotate': {
- 'width': 1000,
- 'height': 1000,
- 'path': 'm922 660c-5 4-9 7-14 11-359 263-580-31-580-31l-102 28 58-400c0 1 1 1 2 2 118 108 351 249 351 249s-62 27-100 42c88 83 222 183 347 122 16-8 30-17 44-27-2 1-4 2-6 4z m36-329c0 0 64 229-88 296-62 27-124 14-175-11 157-78 225-208 249-266 8-19 11-31 11-31 2 5 6 15 11 32-5-13-8-20-8-20z m-775-239c70-31 117-50 198-32-121 80-199 346-199 346l-96-15-58-12c0 0 55-226 155-287z m603 133l-317-139c0 0 4-4 19-14 7-5 24-15 24-15s-177-147-389 4c235-287 536-112 536-112l31-22 100 299-4-1z m-298-153c6-4 14-9 24-15 0 0-17 10-24 15z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'camera': {
- 'width': 1000,
- 'height': 1000,
- 'path': 'm500 450c-83 0-150-67-150-150 0-83 67-150 150-150 83 0 150 67 150 150 0 83-67 150-150 150z m400 150h-120c-16 0-34 13-39 29l-31 93c-6 15-23 28-40 28h-340c-16 0-34-13-39-28l-31-94c-6-15-23-28-40-28h-120c-55 0-100-45-100-100v-450c0-55 45-100 100-100h800c55 0 100 45 100 100v450c0 55-45 100-100 100z m-400-550c-138 0-250 112-250 250 0 138 112 250 250 250 138 0 250-112 250-250 0-138-112-250-250-250z m365 380c-19 0-35 16-35 35 0 19 16 35 35 35 19 0 35-16 35-35 0-19-16-35-35-35z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'movie': {
- 'width': 1000,
- 'height': 1000,
- 'path': 'm938 413l-188-125c0 37-17 71-44 94 64 38 107 107 107 187 0 121-98 219-219 219-121 0-219-98-219-219 0-61 25-117 66-156h-115c30 33 49 76 49 125 0 103-84 187-187 187s-188-84-188-187c0-57 26-107 65-141-38-22-65-62-65-109v-250c0-70 56-126 125-126h500c69 0 125 56 125 126l188-126c34 0 62 28 62 63v375c0 35-28 63-62 63z m-750 0c-69 0-125 56-125 125s56 125 125 125 125-56 125-125-56-125-125-125z m406-1c-87 0-157 70-157 157 0 86 70 156 157 156s156-70 156-156-70-157-156-157z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'question': {
- 'width': 857.1,
- 'height': 1000,
- 'path': 'm500 82v107q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h107q8 0 13 5t5 13z m143 375q0 49-31 91t-77 65-95 23q-136 0-207-119-9-14 4-24l74-55q4-4 10-4 9 0 14 7 30 38 48 51 19 14 48 14 27 0 48-15t21-33q0-21-11-34t-38-25q-35-16-65-48t-29-70v-20q0-8 5-13t13-5h107q8 0 13 5t5 13q0 10 12 27t30 28q18 10 28 16t25 19 25 27 16 34 7 45z m214-107q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'disk': {
- 'width': 857.1,
- 'height': 1000,
- 'path': 'm214-7h429v214h-429v-214z m500 0h72v500q0 8-6 21t-11 20l-157 156q-5 6-19 12t-22 5v-232q0-22-15-38t-38-16h-322q-22 0-37 16t-16 38v232h-72v-714h72v232q0 22 16 38t37 16h465q22 0 38-16t15-38v-232z m-214 518v178q0 8-5 13t-13 5h-107q-7 0-13-5t-5-13v-178q0-8 5-13t13-5h107q7 0 13 5t5 13z m357-18v-518q0-22-15-38t-38-16h-750q-23 0-38 16t-16 38v750q0 22 16 38t38 16h517q23 0 50-12t42-26l156-157q16-15 27-42t11-49z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'lasso': {
- 'width': 1031,
- 'height': 1000,
- 'path': 'm1018 538c-36 207-290 336-568 286-277-48-473-256-436-463 10-57 36-108 76-151-13-66 11-137 68-183 34-28 75-41 114-42l-55-70 0 0c-2-1-3-2-4-3-10-14-8-34 5-45 14-11 34-8 45 4 1 1 2 3 2 5l0 0 113 140c16 11 31 24 45 40 4 3 6 7 8 11 48-3 100 0 151 9 278 48 473 255 436 462z m-624-379c-80 14-149 48-197 96 42 42 109 47 156 9 33-26 47-66 41-105z m-187-74c-19 16-33 37-39 60 50-32 109-55 174-68-42-25-95-24-135 8z m360 75c-34-7-69-9-102-8 8 62-16 128-68 170-73 59-175 54-244-5-9 20-16 40-20 61-28 159 121 317 333 354s407-60 434-217c28-159-121-318-333-355z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'selectbox': {
- 'width': 1000,
- 'height': 1000,
- 'path': 'm0 850l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m285 0l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m-857-286l0-143 143 0 0 143-143 0z m857 0l0-143 143 0 0 143-143 0z m-857-285l0-143 143 0 0 143-143 0z m857 0l0-143 143 0 0 143-143 0z m-857-286l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m285 0l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z',
- 'transform': 'matrix(1 0 0 -1 0 850)'
- },
- 'spikeline': {
- 'width': 1000,
- 'height': 1000,
- 'path': 'M512 409c0-57-46-104-103-104-57 0-104 47-104 104 0 57 47 103 104 103 57 0 103-46 103-103z m-327-39l92 0 0 92-92 0z m-185 0l92 0 0 92-92 0z m370-186l92 0 0 93-92 0z m0-184l92 0 0 92-92 0z',
- 'transform': 'matrix(1.5 0 0 -1.5 0 850)'
- },
- 'newplotlylogo': {
- 'name': 'newplotlylogo',
- 'svg': '
plotly-logomark '
- }
-};
-
-},{}],3:[function(_dereq_,module,exports){
+},{"../src/lib":169}],2:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -215,7 +85,7 @@ module.exports = {
module.exports = _dereq_('../src/traces/bar');
-},{"../src/traces/bar":273}],4:[function(_dereq_,module,exports){
+},{"../src/traces/bar":276}],3:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -228,7 +98,7 @@ module.exports = _dereq_('../src/traces/bar');
module.exports = _dereq_('../src/traces/box');
-},{"../src/traces/box":287}],5:[function(_dereq_,module,exports){
+},{"../src/traces/box":290}],4:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -241,7 +111,7 @@ module.exports = _dereq_('../src/traces/box');
module.exports = _dereq_('../src/traces/contour');
-},{"../src/traces/contour":307}],6:[function(_dereq_,module,exports){
+},{"../src/traces/contour":310}],5:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -254,7 +124,7 @@ module.exports = _dereq_('../src/traces/contour');
module.exports = _dereq_('../src/core');
-},{"../src/core":151}],7:[function(_dereq_,module,exports){
+},{"../src/core":151}],6:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -267,7 +137,7 @@ module.exports = _dereq_('../src/core');
module.exports = _dereq_('../src/traces/heatmap');
-},{"../src/traces/heatmap":323}],8:[function(_dereq_,module,exports){
+},{"../src/traces/heatmap":326}],7:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -280,7 +150,7 @@ module.exports = _dereq_('../src/traces/heatmap');
module.exports = _dereq_('../src/traces/histogram');
-},{"../src/traces/histogram":341}],9:[function(_dereq_,module,exports){
+},{"../src/traces/histogram":344}],8:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -293,7 +163,7 @@ module.exports = _dereq_('../src/traces/histogram');
module.exports = _dereq_('../src/traces/histogram2d');
-},{"../src/traces/histogram2d":347}],10:[function(_dereq_,module,exports){
+},{"../src/traces/histogram2d":350}],9:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -306,7 +176,20 @@ module.exports = _dereq_('../src/traces/histogram2d');
module.exports = _dereq_('../src/traces/histogram2dcontour');
-},{"../src/traces/histogram2dcontour":351}],11:[function(_dereq_,module,exports){
+},{"../src/traces/histogram2dcontour":354}],10:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+module.exports = _dereq_('../src/traces/image');
+
+},{"../src/traces/image":361}],11:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -326,6 +209,7 @@ Plotly.register([
_dereq_('./histogram'),
_dereq_('./histogram2d'),
_dereq_('./histogram2dcontour'),
+ _dereq_('./image'),
_dereq_('./pie'),
_dereq_('./contour'),
_dereq_('./scatterternary'),
@@ -334,7 +218,7 @@ Plotly.register([
module.exports = Plotly;
-},{"./bar":3,"./box":4,"./contour":5,"./core":6,"./heatmap":7,"./histogram":8,"./histogram2d":9,"./histogram2dcontour":10,"./pie":12,"./scatterternary":13,"./violin":14}],12:[function(_dereq_,module,exports){
+},{"./bar":2,"./box":3,"./contour":4,"./core":5,"./heatmap":6,"./histogram":7,"./histogram2d":8,"./histogram2dcontour":9,"./image":10,"./pie":12,"./scatterternary":13,"./violin":14}],12:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -347,7 +231,7 @@ module.exports = Plotly;
module.exports = _dereq_('../src/traces/pie');
-},{"../src/traces/pie":358}],13:[function(_dereq_,module,exports){
+},{"../src/traces/pie":370}],13:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -360,7 +244,7 @@ module.exports = _dereq_('../src/traces/pie');
module.exports = _dereq_('../src/traces/scatterternary');
-},{"../src/traces/scatterternary":396}],14:[function(_dereq_,module,exports){
+},{"../src/traces/scatterternary":410}],14:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -373,7 +257,7 @@ module.exports = _dereq_('../src/traces/scatterternary');
module.exports = _dereq_('../src/traces/violin');
-},{"../src/traces/violin":404}],15:[function(_dereq_,module,exports){
+},{"../src/traces/violin":418}],15:[function(_dereq_,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
@@ -15219,7 +15103,7 @@ module.exports = templatedArray('annotation', {
}
});
-},{"../../plot_api/plot_template":202,"../../plots/cartesian/constants":218,"../../plots/font_attributes":238,"./arrow_paths":35}],37:[function(_dereq_,module,exports){
+},{"../../plot_api/plot_template":203,"../../plots/cartesian/constants":219,"../../plots/font_attributes":239,"./arrow_paths":35}],37:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -15308,7 +15192,7 @@ function calcAxisExpansion(ann, ax) {
ann._extremes[axId] = extremes;
}
-},{"../../lib":168,"../../plots/cartesian/axes":212,"./draw":42}],38:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/cartesian/axes":213,"./draw":42}],38:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -15446,7 +15330,7 @@ function clickData2r(d, ax) {
return ax.type === 'log' ? ax.l2r(d) : ax.d2r(d);
}
-},{"../../lib":168,"../../plot_api/plot_template":202,"../../registry":256}],39:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plot_api/plot_template":203,"../../registry":258}],39:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -15525,7 +15409,7 @@ module.exports = function handleAnnotationCommonDefaults(annIn, annOut, fullLayo
coerce('captureevents', !!hoverText);
};
-},{"../../lib":168,"../color":51}],40:[function(_dereq_,module,exports){
+},{"../../lib":169,"../color":51}],40:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -15588,7 +15472,7 @@ module.exports = function convertCoords(gd, ax, newType, doExtra) {
}
};
-},{"../../lib/to_log_range":191,"fast-isnumeric":18}],41:[function(_dereq_,module,exports){
+},{"../../lib/to_log_range":192,"fast-isnumeric":18}],41:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -15695,7 +15579,7 @@ function handleAnnotationDefaults(annIn, annOut, fullLayout) {
}
}
-},{"../../lib":168,"../../plots/array_container_defaults":208,"../../plots/cartesian/axes":212,"./attributes":36,"./common_defaults":39}],42:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/array_container_defaults":209,"../../plots/cartesian/axes":213,"./attributes":36,"./common_defaults":39}],42:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -15837,24 +15721,25 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
var editTextPosition = edits[options.showarrow ? 'annotationTail' : 'annotationPosition'];
var textEvents = options.captureevents || edits.annotationText || editTextPosition;
+ function makeEventData(initialEvent) {
+ var eventData = {
+ index: index,
+ annotation: options._input,
+ fullAnnotation: options,
+ event: initialEvent
+ };
+ if(subplotId) {
+ eventData.subplotId = subplotId;
+ }
+ return eventData;
+ }
+
var annTextGroupInner = annTextGroup.append('g')
.style('pointer-events', textEvents ? 'all' : null)
.call(setCursor, 'pointer')
.on('click', function() {
gd._dragging = false;
-
- var eventData = {
- index: index,
- annotation: options._input,
- fullAnnotation: options,
- event: d3.event
- };
-
- if(subplotId) {
- eventData.subplotId = subplotId;
- }
-
- gd.emit('plotly_clickannotation', eventData);
+ gd.emit('plotly_clickannotation', makeEventData(d3.event));
});
if(options.hovertext) {
@@ -16089,9 +15974,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
options['_' + axLetter + 'shift'] = textShift;
}
- // We have everything we need for calcAutorange at this point,
- // we can safely exit - unless we're currently dragging the plot
- if(!gd._dragging && annotationIsOffscreen) {
+ if(annotationIsOffscreen) {
annTextGroupInner.remove();
return;
}
@@ -16359,6 +16242,11 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
setCursor(annTextGroupInner, csr);
},
+ clickFn: function(_, initialEvent) {
+ if(options.captureevents) {
+ gd.emit('plotly_clickannotation', makeEventData(initialEvent));
+ }
+ },
doneFn: function() {
setCursor(annTextGroupInner);
Registry.call('_guiRelayout', gd, getUpdateObj());
@@ -16391,7 +16279,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
} else annText.call(textLayout);
}
-},{"../../lib":168,"../../lib/setcursor":187,"../../lib/svg_text_utils":189,"../../plot_api/plot_template":202,"../../plots/cartesian/axes":212,"../../plots/plots":244,"../../registry":256,"../color":51,"../dragelement":69,"../drawing":72,"../fx":90,"./draw_arrow_head":43,"d3":16}],43:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../lib/setcursor":188,"../../lib/svg_text_utils":190,"../../plot_api/plot_template":203,"../../plots/cartesian/axes":213,"../../plots/plots":245,"../../registry":258,"../color":51,"../dragelement":69,"../drawing":72,"../fx":89,"./draw_arrow_head":43,"d3":16}],43:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -16576,7 +16464,7 @@ module.exports = {
convertCoords: _dereq_('./convert_coords')
};
-},{"../../plots/cartesian/include_components":222,"./attributes":36,"./calc_autorange":37,"./click":38,"./convert_coords":40,"./defaults":41,"./draw":42}],45:[function(_dereq_,module,exports){
+},{"../../plots/cartesian/include_components":223,"./attributes":36,"./calc_autorange":37,"./click":38,"./convert_coords":40,"./defaults":41,"./draw":42}],45:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -16588,12 +16476,12 @@ module.exports = {
'use strict';
-var annAtts = _dereq_('../annotations/attributes');
+var annAttrs = _dereq_('../annotations/attributes');
var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll;
var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray;
module.exports = overrideAll(templatedArray('annotation', {
- visible: annAtts.visible,
+ visible: annAttrs.visible,
x: {
valType: 'any',
@@ -16620,41 +16508,41 @@ module.exports = overrideAll(templatedArray('annotation', {
},
- xanchor: annAtts.xanchor,
- xshift: annAtts.xshift,
- yanchor: annAtts.yanchor,
- yshift: annAtts.yshift,
+ xanchor: annAttrs.xanchor,
+ xshift: annAttrs.xshift,
+ yanchor: annAttrs.yanchor,
+ yshift: annAttrs.yshift,
- text: annAtts.text,
- textangle: annAtts.textangle,
- font: annAtts.font,
- width: annAtts.width,
- height: annAtts.height,
- opacity: annAtts.opacity,
- align: annAtts.align,
- valign: annAtts.valign,
- bgcolor: annAtts.bgcolor,
- bordercolor: annAtts.bordercolor,
- borderpad: annAtts.borderpad,
- borderwidth: annAtts.borderwidth,
- showarrow: annAtts.showarrow,
- arrowcolor: annAtts.arrowcolor,
- arrowhead: annAtts.arrowhead,
- startarrowhead: annAtts.startarrowhead,
- arrowside: annAtts.arrowside,
- arrowsize: annAtts.arrowsize,
- startarrowsize: annAtts.startarrowsize,
- arrowwidth: annAtts.arrowwidth,
- standoff: annAtts.standoff,
- startstandoff: annAtts.startstandoff,
- hovertext: annAtts.hovertext,
- hoverlabel: annAtts.hoverlabel,
- captureevents: annAtts.captureevents,
+ text: annAttrs.text,
+ textangle: annAttrs.textangle,
+ font: annAttrs.font,
+ width: annAttrs.width,
+ height: annAttrs.height,
+ opacity: annAttrs.opacity,
+ align: annAttrs.align,
+ valign: annAttrs.valign,
+ bgcolor: annAttrs.bgcolor,
+ bordercolor: annAttrs.bordercolor,
+ borderpad: annAttrs.borderpad,
+ borderwidth: annAttrs.borderwidth,
+ showarrow: annAttrs.showarrow,
+ arrowcolor: annAttrs.arrowcolor,
+ arrowhead: annAttrs.arrowhead,
+ startarrowhead: annAttrs.startarrowhead,
+ arrowside: annAttrs.arrowside,
+ arrowsize: annAttrs.arrowsize,
+ startarrowsize: annAttrs.startarrowsize,
+ arrowwidth: annAttrs.arrowwidth,
+ standoff: annAttrs.standoff,
+ startstandoff: annAttrs.startstandoff,
+ hovertext: annAttrs.hovertext,
+ hoverlabel: annAttrs.hoverlabel,
+ captureevents: annAttrs.captureevents,
// maybes later?
- // clicktoshow: annAtts.clicktoshow,
- // xclick: annAtts.xclick,
- // yclick: annAtts.yclick,
+ // clicktoshow: annAttrs.clicktoshow,
+ // xclick: annAttrs.xclick,
+ // yclick: annAttrs.yclick,
// not needed!
// axref: 'pixel'
@@ -16664,7 +16552,7 @@ module.exports = overrideAll(templatedArray('annotation', {
// zref: 'z'
}), 'calc', 'from-root');
-},{"../../plot_api/edit_types":195,"../../plot_api/plot_template":202,"../annotations/attributes":36}],46:[function(_dereq_,module,exports){
+},{"../../plot_api/edit_types":196,"../../plot_api/plot_template":203,"../annotations/attributes":36}],46:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -16729,7 +16617,7 @@ function mockAnnAxes(ann, scene) {
};
}
-},{"../../lib":168,"../../plots/cartesian/axes":212}],47:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/cartesian/axes":213}],47:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -16805,7 +16693,7 @@ function handleAnnotationDefaults(annIn, annOut, sceneLayout, opts) {
}
}
-},{"../../lib":168,"../../plots/array_container_defaults":208,"../../plots/cartesian/axes":212,"../annotations/common_defaults":39,"./attributes":45}],48:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/array_container_defaults":209,"../../plots/cartesian/axes":213,"../annotations/common_defaults":39,"./attributes":45}],48:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -16857,7 +16745,7 @@ module.exports = function draw(scene) {
}
};
-},{"../../plots/gl3d/project":241,"../annotations/draw":42}],49:[function(_dereq_,module,exports){
+},{"../../plots/gl3d/project":242,"../annotations/draw":42}],49:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -16905,7 +16793,7 @@ function includeGL3D(layoutIn, layoutOut) {
}
}
-},{"../../lib":168,"../../registry":256,"./attributes":45,"./convert":46,"./defaults":47,"./draw":48}],50:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../registry":258,"./attributes":45,"./convert":46,"./defaults":47,"./draw":48}],50:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -17298,7 +17186,7 @@ module.exports = overrideAll({
}
}, 'colorbars', 'from-root');
-},{"../../lib/extend":162,"../../plot_api/edit_types":195,"../../plots/cartesian/layout_attributes":224,"../../plots/font_attributes":238}],53:[function(_dereq_,module,exports){
+},{"../../lib/extend":164,"../../plot_api/edit_types":196,"../../plots/cartesian/layout_attributes":225,"../../plots/font_attributes":239}],53:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -17392,7 +17280,7 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
coerce('title.side');
};
-},{"../../lib":168,"../../plot_api/plot_template":202,"../../plots/cartesian/tick_label_defaults":231,"../../plots/cartesian/tick_mark_defaults":232,"../../plots/cartesian/tick_value_defaults":233,"./attributes":52}],55:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plot_api/plot_template":203,"../../plots/cartesian/tick_label_defaults":232,"../../plots/cartesian/tick_mark_defaults":233,"../../plots/cartesian/tick_value_defaults":234,"./attributes":52}],55:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -17623,7 +17511,8 @@ function drawColorBar(g, opts, gd) {
opts._xLeftFrac = xLeftFrac;
opts._yBottomFrac = yBottomFrac;
- var ax = mockColorBarAxis(gd, opts, zrange);
+ // stash mocked axis for contour label formatting
+ var ax = opts._axis = mockColorBarAxis(gd, opts, zrange);
// position can't go in through supplyDefaults
// because that restricts it to [0,1]
@@ -18117,7 +18006,7 @@ module.exports = {
draw: draw
};
-},{"../../constants/alignment":146,"../../lib":168,"../../lib/extend":162,"../../lib/setcursor":187,"../../lib/svg_text_utils":189,"../../plots/cartesian/axes":212,"../../plots/cartesian/axis_defaults":214,"../../plots/cartesian/layout_attributes":224,"../../plots/cartesian/position_defaults":227,"../../plots/plots":244,"../../registry":256,"../color":51,"../colorscale/helpers":62,"../dragelement":69,"../drawing":72,"../titles":139,"./constants":53,"d3":16,"tinycolor2":34}],56:[function(_dereq_,module,exports){
+},{"../../constants/alignment":145,"../../lib":169,"../../lib/extend":164,"../../lib/setcursor":188,"../../lib/svg_text_utils":190,"../../plots/cartesian/axes":213,"../../plots/cartesian/axis_defaults":215,"../../plots/cartesian/layout_attributes":225,"../../plots/cartesian/position_defaults":228,"../../plots/plots":245,"../../registry":258,"../color":51,"../colorscale/helpers":62,"../dragelement":69,"../drawing":72,"../titles":138,"./constants":53,"d3":16,"tinycolor2":34}],56:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -18136,7 +18025,7 @@ module.exports = function hasColorbar(container) {
return Lib.isPlainObject(container.colorbar);
};
-},{"../../lib":168}],57:[function(_dereq_,module,exports){
+},{"../../lib":169}],57:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -18366,7 +18255,7 @@ module.exports = function colorScaleAttrs(context, opts) {
return attrs;
};
-},{"../../lib/regex":183,"../colorbar/attributes":52,"./scales.js":66}],59:[function(_dereq_,module,exports){
+},{"../../lib/regex":184,"../colorbar/attributes":52,"./scales.js":66}],59:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -18445,7 +18334,7 @@ module.exports = function calc(gd, trace, opts) {
}
};
-},{"../../lib":168,"./helpers":62,"fast-isnumeric":18}],60:[function(_dereq_,module,exports){
+},{"../../lib":169,"./helpers":62,"fast-isnumeric":18}],60:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -18468,7 +18357,7 @@ module.exports = function crossTraceDefaults(fullData, fullLayout) {
}
}
- function relinkColorAtts(outerCont, cbOpt) {
+ function relinkColorAttrs(outerCont, cbOpt) {
var cont = cbOpt.container ?
Lib.nestedProperty(outerCont, cbOpt.container).get() :
outerCont;
@@ -18501,15 +18390,15 @@ module.exports = function crossTraceDefaults(fullData, fullLayout) {
if(cbOpts) {
if(Array.isArray(cbOpts)) {
for(var j = 0; j < cbOpts.length; j++) {
- relinkColorAtts(trace, cbOpts[j]);
+ relinkColorAttrs(trace, cbOpts[j]);
}
} else {
- relinkColorAtts(trace, cbOpts);
+ relinkColorAttrs(trace, cbOpts);
}
}
if(hasColorscale(trace, 'marker.line')) {
- relinkColorAtts(trace, {
+ relinkColorAttrs(trace, {
container: 'marker.line',
min: 'cmin',
max: 'cmax'
@@ -18518,11 +18407,11 @@ module.exports = function crossTraceDefaults(fullData, fullLayout) {
}
for(var k in fullLayout._colorAxes) {
- relinkColorAtts(fullLayout[k], {min: 'cmin', max: 'cmax'});
+ relinkColorAttrs(fullLayout[k], {min: 'cmin', max: 'cmax'});
}
};
-},{"../../lib":168,"./helpers":62}],61:[function(_dereq_,module,exports){
+},{"../../lib":169,"./helpers":62}],61:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -18644,7 +18533,7 @@ module.exports = function colorScaleDefaults(parentContIn, parentContOut, layout
}
};
-},{"../../lib":168,"../../registry":256,"../colorbar/defaults":54,"../colorbar/has_colorbar":56,"./scales":66,"fast-isnumeric":18}],62:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../registry":258,"../colorbar/defaults":54,"../colorbar/has_colorbar":56,"./scales":66,"fast-isnumeric":18}],62:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -18664,11 +18553,11 @@ var Color = _dereq_('../color');
var isValidScale = _dereq_('./scales').isValid;
-function hasColorscale(trace, containerStr) {
+function hasColorscale(trace, containerStr, colorKey) {
var container = containerStr ?
Lib.nestedProperty(trace, containerStr).get() || {} :
trace;
- var color = container.color;
+ var color = container[colorKey || 'color'];
var isArrayWithOneNumber = false;
if(Lib.isArrayOrTypedArray(color)) {
@@ -18884,7 +18773,7 @@ module.exports = {
makeColorScaleFuncFromTrace: makeColorScaleFuncFromTrace
};
-},{"../../lib":168,"../color":51,"./scales":66,"d3":16,"fast-isnumeric":18,"tinycolor2":34}],63:[function(_dereq_,module,exports){
+},{"../../lib":169,"../color":51,"./scales":66,"d3":16,"fast-isnumeric":18,"tinycolor2":34}],63:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -18987,7 +18876,7 @@ module.exports = {
}))
};
-},{"../../lib/extend":162,"./attributes":58,"./scales":66}],65:[function(_dereq_,module,exports){
+},{"../../lib/extend":164,"./attributes":58,"./scales":66}],65:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -19038,7 +18927,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) {
}
};
-},{"../../lib":168,"../../plot_api/plot_template":202,"./defaults":61,"./layout_attributes":64}],66:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plot_api/plot_template":203,"./defaults":61,"./layout_attributes":64}],66:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -19313,7 +19202,7 @@ module.exports = function getCursor(x, y, xanchor, yanchor) {
return cursorset[y][x];
};
-},{"../../lib":168}],69:[function(_dereq_,module,exports){
+},{"../../lib":169}],69:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -19330,7 +19219,6 @@ var supportsPassive = _dereq_('has-passive-events');
var removeElement = _dereq_('../../lib').removeElement;
var constants = _dereq_('../../plots/cartesian/constants');
-var interactConstants = _dereq_('../../constants/interactions');
var dragElement = module.exports = {};
@@ -19398,7 +19286,7 @@ dragElement.unhoverRaw = unhover.raw;
dragElement.init = function init(options) {
var gd = options.gd;
var numClicks = 1;
- var DBLCLICKDELAY = interactConstants.DBLCLICKDELAY;
+ var doubleClickDelay = gd._context.doubleClickDelay;
var element = options.element;
var startX,
@@ -19453,7 +19341,7 @@ dragElement.init = function init(options) {
}
newMouseDownTime = (new Date()).getTime();
- if(newMouseDownTime - gd._mouseDownTime < DBLCLICKDELAY) {
+ if(newMouseDownTime - gd._mouseDownTime < doubleClickDelay) {
// in a click train
numClicks += 1;
} else {
@@ -19480,7 +19368,7 @@ dragElement.init = function init(options) {
if(options.dragmode !== false) {
e.preventDefault();
document.addEventListener('mousemove', onMove);
- document.addEventListener('touchmove', onMove);
+ document.addEventListener('touchmove', onMove, {passive: false});
}
return;
@@ -19539,7 +19427,7 @@ dragElement.init = function init(options) {
// don't count as a dblClick unless the mouseUp is also within
// the dblclick delay
- if((new Date()).getTime() - gd._mouseDownTime > DBLCLICKDELAY) {
+ if((new Date()).getTime() - gd._mouseDownTime > doubleClickDelay) {
numClicks = Math.max(numClicks - 1, 1);
}
@@ -19606,7 +19494,7 @@ function pointerOffset(e) {
);
}
-},{"../../constants/interactions":148,"../../lib":168,"../../plots/cartesian/constants":218,"./align":67,"./cursor":68,"./unhover":70,"has-hover":20,"has-passive-events":21,"mouse-event-offset":24}],70:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/cartesian/constants":219,"./align":67,"./cursor":68,"./unhover":70,"has-hover":20,"has-passive-events":21,"mouse-event-offset":24}],70:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -19615,19 +19503,16 @@ function pointerOffset(e) {
* LICENSE file in the root directory of this source tree.
*/
-
'use strict';
-
var Events = _dereq_('../../lib/events');
var throttle = _dereq_('../../lib/throttle');
-var getGraphDiv = _dereq_('../../lib/get_graph_div');
+var getGraphDiv = _dereq_('../../lib/dom').getGraphDiv;
var hoverConstants = _dereq_('../fx/constants');
var unhover = module.exports = {};
-
unhover.wrapped = function(gd, evt, subplot) {
gd = getGraphDiv(gd);
@@ -19664,7 +19549,7 @@ unhover.raw = function raw(gd, evt) {
}
};
-},{"../../lib/events":161,"../../lib/get_graph_div":166,"../../lib/throttle":190,"../fx/constants":84}],71:[function(_dereq_,module,exports){
+},{"../../lib/dom":162,"../../lib/events":163,"../../lib/throttle":191,"../fx/constants":84}],71:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -19718,6 +19603,7 @@ var DESELECTDIM = _dereq_('../../constants/interactions').DESELECTDIM;
var subTypes = _dereq_('../../traces/scatter/subtypes');
var makeBubbleSizeFn = _dereq_('../../traces/scatter/make_bubble_size_func');
+var appendArrayPointValue = _dereq_('../../components/fx/helpers').appendArrayPointValue;
var drawing = module.exports = {};
@@ -20133,7 +20019,7 @@ drawing.singlePointStyle = function(d, sel, trace, fns, gd) {
fill: 'none'
});
} else {
- sel.style('stroke-width', lineWidth + 'px');
+ sel.style('stroke-width', (d.isBlank ? 0 : lineWidth) + 'px');
var markerGradient = marker.gradient;
@@ -20375,21 +20261,34 @@ drawing.textPointStyle = function(s, trace, gd) {
if(!s.size()) return;
var selectedTextColorFn;
-
if(trace.selectedpoints) {
var fns = drawing.makeSelectedTextStyleFns(trace);
selectedTextColorFn = fns.selectedTextColorFn;
}
+ var texttemplate = trace.texttemplate;
+ var fullLayout = gd._fullLayout;
+
s.each(function(d) {
var p = d3.select(this);
- var text = Lib.extractOption(d, trace, 'tx', 'text');
+
+ var text = texttemplate ?
+ Lib.extractOption(d, trace, 'txt', 'texttemplate') :
+ Lib.extractOption(d, trace, 'tx', 'text');
if(!text && text !== 0) {
p.remove();
return;
}
+ if(texttemplate) {
+ var labels = trace._module.formatLabels ? trace._module.formatLabels(d, trace, fullLayout) : {};
+ var pointValues = {};
+ appendArrayPointValue(pointValues, trace, d.i);
+ var meta = trace._meta || {};
+ text = Lib.texttemplateString(text, labels, fullLayout._d3locale, pointValues, d, meta);
+ }
+
var pos = d.tp || trace.textposition;
var fontSize = extracTextFontSize(d, trace);
var fontColor = selectedTextColorFn ?
@@ -20838,7 +20737,7 @@ drawing.setTextPointsScale = function(selection, xScale, yScale) {
});
};
-},{"../../constants/alignment":146,"../../constants/interactions":148,"../../constants/xmlns_namespaces":150,"../../lib":168,"../../lib/svg_text_utils":189,"../../registry":256,"../../traces/scatter/make_bubble_size_func":381,"../../traces/scatter/subtypes":388,"../color":51,"../colorscale":63,"./symbol_defs":73,"d3":16,"fast-isnumeric":18,"tinycolor2":34}],73:[function(_dereq_,module,exports){
+},{"../../components/fx/helpers":86,"../../constants/alignment":145,"../../constants/interactions":148,"../../constants/xmlns_namespaces":150,"../../lib":169,"../../lib/svg_text_utils":190,"../../registry":258,"../../traces/scatter/make_bubble_size_func":394,"../../traces/scatter/subtypes":401,"../color":51,"../colorscale":63,"./symbol_defs":73,"d3":16,"fast-isnumeric":18,"tinycolor2":34}],73:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -21527,7 +21426,7 @@ function calcOneAxis(calcTrace, trace, axis, coord) {
baseExtremes.max = baseExtremes.max.concat(extremes.max);
}
-},{"../../lib":168,"../../plots/cartesian/axes":212,"../../registry":256,"./compute_error":76,"fast-isnumeric":18}],76:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/cartesian/axes":213,"../../registry":258,"./compute_error":76,"fast-isnumeric":18}],76:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -21703,7 +21602,7 @@ module.exports = function(traceIn, traceOut, defaultColor, opts) {
}
};
-},{"../../lib":168,"../../plot_api/plot_template":202,"../../registry":256,"./attributes":74,"fast-isnumeric":18}],78:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plot_api/plot_template":203,"../../registry":258,"./attributes":74,"fast-isnumeric":18}],78:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -21772,7 +21671,7 @@ function hoverInfo(calcPoint, trace, hoverPoint) {
}
}
-},{"../../lib":168,"../../plot_api/edit_types":195,"./attributes":74,"./calc":75,"./compute_error":76,"./defaults":77,"./plot":79,"./style":80}],79:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plot_api/edit_types":196,"./attributes":74,"./calc":75,"./compute_error":76,"./defaults":77,"./plot":79,"./style":80}],79:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -21944,7 +21843,7 @@ function errorCoords(d, xa, ya) {
return out;
}
-},{"../../traces/scatter/subtypes":388,"../drawing":72,"d3":16,"fast-isnumeric":18}],80:[function(_dereq_,module,exports){
+},{"../../traces/scatter/subtypes":401,"../drawing":72,"d3":16,"fast-isnumeric":18}],80:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -22017,7 +21916,7 @@ module.exports = {
}
};
-},{"../../lib/extend":162,"../../plots/font_attributes":238,"./layout_attributes":91}],82:[function(_dereq_,module,exports){
+},{"../../lib/extend":164,"../../plots/font_attributes":239,"./layout_attributes":90}],82:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -22076,7 +21975,7 @@ function paste(traceAttr, cd, cdAttr, fn) {
}
}
-},{"../../lib":168,"../../registry":256}],83:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../registry":258}],83:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -22113,7 +22012,7 @@ module.exports = function click(gd, evt, subplot) {
}
};
-},{"../../registry":256,"./hover":87}],84:[function(_dereq_,module,exports){
+},{"../../registry":258,"./hover":87}],84:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -22171,7 +22070,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
handleHoverLabelDefaults(traceIn, traceOut, coerce, opts);
};
-},{"../../lib":168,"./attributes":81,"./hoverlabel_defaults":88}],86:[function(_dereq_,module,exports){
+},{"../../lib":169,"./attributes":81,"./hoverlabel_defaults":88}],86:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -22413,7 +22312,7 @@ function getPointData(val, pointNumber) {
}
}
-},{"../../lib":168}],87:[function(_dereq_,module,exports){
+},{"../../lib":169}],87:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -22640,24 +22539,20 @@ function _hover(gd, evt, subplot, noHoverEvent) {
for(var i = 0; i < len; i++) {
var spId = subplots[i];
- // 'cartesian' case
- var plotObj = plots[spId];
- if(plotObj) {
+ if(plots[spId]) {
+ // 'cartesian' case
supportsCompare = true;
-
- // TODO make sure that fullLayout_plots axis refs
- // get updated properly so that we don't have
- // to use Axes.getFromId in general.
-
- xaArray[i] = Axes.getFromId(gd, plotObj.xaxis._id);
- yaArray[i] = Axes.getFromId(gd, plotObj.yaxis._id);
- continue;
+ xaArray[i] = plots[spId].xaxis;
+ yaArray[i] = plots[spId].yaxis;
+ } else if(fullLayout[spId] && fullLayout[spId]._subplot) {
+ // other subplot types
+ var _subplot = fullLayout[spId]._subplot;
+ xaArray[i] = _subplot.xaxis;
+ yaArray[i] = _subplot.yaxis;
+ } else {
+ Lib.warn('Unrecognized subplot: ' + spId);
+ return;
}
-
- // other subplot types
- var _subplot = fullLayout[spId]._subplot;
- xaArray[i] = _subplot.xaxis;
- yaArray[i] = _subplot.yaxis;
}
var hovermode = evt.hovermode || fullLayout.hovermode;
@@ -23021,7 +22916,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
var result = dragElement.unhoverRaw(gd, evt);
if(hasCartesian && ((spikePoints.hLinePoint !== null) || (spikePoints.vLinePoint !== null))) {
if(spikesChanged(oldspikepoints)) {
- createSpikelines(spikePoints, spikelineOpts);
+ createSpikelines(gd, spikePoints, spikelineOpts);
}
}
return result;
@@ -23029,7 +22924,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
if(hasCartesian) {
if(spikesChanged(oldspikepoints)) {
- createSpikelines(spikePoints, spikelineOpts);
+ createSpikelines(gd, spikePoints, spikelineOpts);
}
}
@@ -23192,6 +23087,11 @@ function createHoverText(hoverData, opts, gd) {
var commonBgColor = commonLabelOpts.bgcolor || Color.defaultLine;
var commonStroke = commonLabelOpts.bordercolor || Color.contrast(commonBgColor);
var contrastColor = Color.contrast(commonBgColor);
+ var commonLabelFont = {
+ family: commonLabelOpts.font.family || fontFamily,
+ size: commonLabelOpts.font.size || fontSize,
+ color: commonLabelOpts.font.color || contrastColor
+ };
lpath.style({
fill: commonBgColor,
@@ -23199,41 +23099,76 @@ function createHoverText(hoverData, opts, gd) {
});
ltext.text(t0)
- .call(Drawing.font,
- commonLabelOpts.font.family || fontFamily,
- commonLabelOpts.font.size || fontSize,
- commonLabelOpts.font.color || contrastColor
- )
+ .call(Drawing.font, commonLabelFont)
.call(svgTextUtils.positionText, 0, 0)
.call(svgTextUtils.convertToTspans, gd);
label.attr('transform', '');
var tbb = ltext.node().getBoundingClientRect();
+ var lx, ly;
+
if(hovermode === 'x') {
+ var topsign = xa.side === 'top' ? '-' : '';
+
ltext.attr('text-anchor', 'middle')
.call(svgTextUtils.positionText, 0, (xa.side === 'top' ?
(outerTop - tbb.bottom - HOVERARROWSIZE - HOVERTEXTPAD) :
(outerTop - tbb.top + HOVERARROWSIZE + HOVERTEXTPAD)));
- var topsign = xa.side === 'top' ? '-' : '';
- lpath.attr('d', 'M0,0' +
- 'L' + HOVERARROWSIZE + ',' + topsign + HOVERARROWSIZE +
- 'H' + (HOVERTEXTPAD + tbb.width / 2) +
- 'v' + topsign + (HOVERTEXTPAD * 2 + tbb.height) +
- 'H-' + (HOVERTEXTPAD + tbb.width / 2) +
- 'V' + topsign + HOVERARROWSIZE + 'H-' + HOVERARROWSIZE + 'Z');
+ lx = xa._offset + (c0.x0 + c0.x1) / 2;
+ ly = ya._offset + (xa.side === 'top' ? 0 : ya._length);
- label.attr('transform', 'translate(' +
- (xa._offset + (c0.x0 + c0.x1) / 2) + ',' +
- (ya._offset + (xa.side === 'top' ? 0 : ya._length)) + ')');
+ var halfWidth = tbb.width / 2 + HOVERTEXTPAD;
+
+ if(lx < halfWidth) {
+ lx = halfWidth;
+
+ lpath.attr('d', 'M-' + (halfWidth - HOVERARROWSIZE) + ',0' +
+ 'L-' + (halfWidth - HOVERARROWSIZE * 2) + ',' + topsign + HOVERARROWSIZE +
+ 'H' + (HOVERTEXTPAD + tbb.width / 2) +
+ 'v' + topsign + (HOVERTEXTPAD * 2 + tbb.height) +
+ 'H-' + halfWidth +
+ 'V' + topsign + HOVERARROWSIZE +
+ 'Z');
+ } else if(lx > (fullLayout.width - halfWidth)) {
+ lx = fullLayout.width - halfWidth;
+
+ lpath.attr('d', 'M' + (halfWidth - HOVERARROWSIZE) + ',0' +
+ 'L' + halfWidth + ',' + topsign + HOVERARROWSIZE +
+ 'v' + topsign + (HOVERTEXTPAD * 2 + tbb.height) +
+ 'H-' + halfWidth +
+ 'V' + topsign + HOVERARROWSIZE +
+ 'H' + (halfWidth - HOVERARROWSIZE * 2) + 'Z');
+ } else {
+ lpath.attr('d', 'M0,0' +
+ 'L' + HOVERARROWSIZE + ',' + topsign + HOVERARROWSIZE +
+ 'H' + (HOVERTEXTPAD + tbb.width / 2) +
+ 'v' + topsign + (HOVERTEXTPAD * 2 + tbb.height) +
+ 'H-' + (HOVERTEXTPAD + tbb.width / 2) +
+ 'V' + topsign + HOVERARROWSIZE +
+ 'H-' + HOVERARROWSIZE + 'Z');
+ }
} else {
- ltext.attr('text-anchor', ya.side === 'right' ? 'start' : 'end')
- .call(svgTextUtils.positionText,
- (ya.side === 'right' ? 1 : -1) * (HOVERTEXTPAD + HOVERARROWSIZE),
- outerTop - tbb.top - tbb.height / 2);
+ var anchor;
+ var sgn;
+ var leftsign;
+ if(ya.side === 'right') {
+ anchor = 'start';
+ sgn = 1;
+ leftsign = '';
+ lx = xa._offset + xa._length;
+ } else {
+ anchor = 'end';
+ sgn = -1;
+ leftsign = '-';
+ lx = xa._offset;
+ }
+
+ ly = ya._offset + (c0.y0 + c0.y1) / 2;
+
+ ltext.attr('text-anchor', anchor);
- var leftsign = ya.side === 'right' ? '' : '-';
lpath.attr('d', 'M0,0' +
'L' + leftsign + HOVERARROWSIZE + ',' + HOVERARROWSIZE +
'V' + (HOVERTEXTPAD + tbb.height / 2) +
@@ -23241,10 +23176,49 @@ function createHoverText(hoverData, opts, gd) {
'V-' + (HOVERTEXTPAD + tbb.height / 2) +
'H' + leftsign + HOVERARROWSIZE + 'V-' + HOVERARROWSIZE + 'Z');
- label.attr('transform', 'translate(' +
- (xa._offset + (ya.side === 'right' ? xa._length : 0)) + ',' +
- (ya._offset + (c0.y0 + c0.y1) / 2) + ')');
+ var halfHeight = tbb.height / 2;
+ var lty = outerTop - tbb.top - halfHeight;
+ var clipId = 'clip' + fullLayout._uid + 'commonlabel' + ya._id;
+ var clipPath;
+
+ if(lx < (tbb.width + 2 * HOVERTEXTPAD + HOVERARROWSIZE)) {
+ clipPath = 'M-' + (HOVERARROWSIZE + HOVERTEXTPAD) + '-' + halfHeight +
+ 'h-' + (tbb.width - HOVERTEXTPAD) +
+ 'V' + halfHeight +
+ 'h' + (tbb.width - HOVERTEXTPAD) + 'Z';
+
+ var ltx = tbb.width - lx + HOVERTEXTPAD;
+ svgTextUtils.positionText(ltext, ltx, lty);
+
+ // shift each line (except the longest) so that start-of-line
+ // is always visible
+ if(anchor === 'end') {
+ ltext.selectAll('tspan').each(function() {
+ var s = d3.select(this);
+ var dummy = Drawing.tester.append('text')
+ .text(s.text())
+ .call(Drawing.font, commonLabelFont);
+ var dummyBB = dummy.node().getBoundingClientRect();
+ if(Math.round(dummyBB.width) < Math.round(tbb.width)) {
+ s.attr('x', ltx - dummyBB.width);
+ }
+ dummy.remove();
+ });
+ }
+ } else {
+ svgTextUtils.positionText(ltext, sgn * (HOVERTEXTPAD + HOVERARROWSIZE), lty);
+ clipPath = null;
+ }
+
+ var textClip = fullLayout._topclips.selectAll('#' + clipId).data(clipPath ? [0] : []);
+ textClip.enter().append('clipPath').attr('id', clipId).append('path');
+ textClip.exit().remove();
+ textClip.select('path').attr('d', clipPath);
+ Drawing.setClipUrl(ltext, clipPath ? clipId : null, gd);
}
+
+ label.attr('transform', 'translate(' + lx + ',' + ly + ')');
+
// remove the "close but not quite" points
// because of error bars, only take up to a space
hoverData = hoverData.filter(function(d) {
@@ -23255,10 +23229,11 @@ function createHoverText(hoverData, opts, gd) {
// show all the individual labels
-
// first create the objects
var hoverLabels = container.selectAll('g.hovertext')
.data(hoverData, function(d) {
+ // N.B. when multiple items have the same result key-function value,
+ // only the first of those items in hoverData gets rendered
return [d.trace.index, d.index, d.x0, d.y0, d.name, d.attr, d.xa, d.ya || ''].join(',');
});
hoverLabels.enter().append('g')
@@ -23312,11 +23287,15 @@ function createHoverText(hoverData, opts, gd) {
if(d.zLabel !== undefined) {
if(d.xLabel !== undefined) text += 'x: ' + d.xLabel + '
';
if(d.yLabel !== undefined) text += 'y: ' + d.yLabel + '
';
- text += (text ? 'z: ' : '') + d.zLabel;
+ if(d.trace.type !== 'choropleth' && d.trace.type !== 'choroplethmapbox') {
+ text += (text ? 'z: ' : '') + d.zLabel;
+ }
} else if(showCommonLabel && d[hovermode + 'Label'] === t0) {
text = d[(hovermode === 'x' ? 'y' : 'x') + 'Label'] || '';
} else if(d.xLabel === undefined) {
- if(d.yLabel !== undefined && d.trace.type !== 'scattercarpet') text = d.yLabel;
+ if(d.yLabel !== undefined && d.trace.type !== 'scattercarpet') {
+ text = d.yLabel;
+ }
} else if(d.yLabel === undefined) text = d.xLabel;
else text = '(' + d.xLabel + ', ' + d.yLabel + ')';
@@ -23471,22 +23450,25 @@ function createHoverText(hoverData, opts, gd) {
// know what happens if the group spans all the way from one edge to
// the other, though it hardly matters - there's just too much
// information then.
-function hoverAvoidOverlaps(hoverLabels, ax, fullLayout) {
+function hoverAvoidOverlaps(hoverLabels, axKey, fullLayout) {
var nummoves = 0;
var axSign = 1;
var nLabels = hoverLabels.size();
// make groups of touching points
var pointgroups = new Array(nLabels);
+ var k = 0;
- hoverLabels.each(function(d, i) {
- var axis = d[ax];
- var axIsX = axis._id.charAt(0) === 'x';
- var rng = axis.range;
- if(!i && rng && ((rng[0] > rng[1]) !== axIsX)) axSign = -1;
- pointgroups[i] = [{
+ hoverLabels.each(function(d) {
+ var ax = d[axKey];
+ var axIsX = ax._id.charAt(0) === 'x';
+ var rng = ax.range;
+
+ if(k === 0 && rng && ((rng[0] > rng[1]) !== axIsX)) {
+ axSign = -1;
+ }
+ pointgroups[k++] = [{
datum: d,
- i: i,
traceIndex: d.trace.index,
dp: 0,
pos: d.pos,
@@ -23804,9 +23786,10 @@ function cleanPoint(d, hovermode) {
return d;
}
-function createSpikelines(closestPoints, opts) {
+function createSpikelines(gd, closestPoints, opts) {
var container = opts.container;
var fullLayout = opts.fullLayout;
+ var gs = fullLayout._size;
var evt = opts.event;
var showY = !!closestPoints.hLinePoint;
var showX = !!closestPoints.vLinePoint;
@@ -23841,8 +23824,7 @@ function createSpikelines(closestPoints, opts) {
var yMode = ya.spikemode;
var yThickness = ya.spikethickness;
var yColor = ya.spikecolor || dfltHLineColor;
- var yBB = ya._boundingBox;
- var xEdge = ((yBB.left + yBB.right) / 2) < hLinePointX ? yBB.right : yBB.left;
+ var xEdge = Axes.getPxPosition(gd, ya);
var xBase, xEndSpike;
if(yMode.indexOf('toaxis') !== -1 || yMode.indexOf('across') !== -1) {
@@ -23851,8 +23833,14 @@ function createSpikelines(closestPoints, opts) {
xEndSpike = hLinePointX;
}
if(yMode.indexOf('across') !== -1) {
- xBase = ya._counterSpan[0];
- xEndSpike = ya._counterSpan[1];
+ var xAcross0 = ya._counterDomainMin;
+ var xAcross1 = ya._counterDomainMax;
+ if(ya.anchor === 'free') {
+ xAcross0 = Math.min(xAcross0, ya.position);
+ xAcross1 = Math.max(xAcross1, ya.position);
+ }
+ xBase = gs.l + xAcross0 * gs.w;
+ xEndSpike = gs.l + xAcross1 * gs.w;
}
// Foreground horizontal line (to y-axis)
@@ -23915,8 +23903,7 @@ function createSpikelines(closestPoints, opts) {
var xMode = xa.spikemode;
var xThickness = xa.spikethickness;
var xColor = xa.spikecolor || dfltVLineColor;
- var xBB = xa._boundingBox;
- var yEdge = ((xBB.top + xBB.bottom) / 2) < vLinePointY ? xBB.bottom : xBB.top;
+ var yEdge = Axes.getPxPosition(gd, xa);
var yBase, yEndSpike;
if(xMode.indexOf('toaxis') !== -1 || xMode.indexOf('across') !== -1) {
@@ -23925,8 +23912,14 @@ function createSpikelines(closestPoints, opts) {
yEndSpike = vLinePointY;
}
if(xMode.indexOf('across') !== -1) {
- yBase = xa._counterSpan[0];
- yEndSpike = xa._counterSpan[1];
+ var yAcross0 = xa._counterDomainMin;
+ var yAcross1 = xa._counterDomainMax;
+ if(xa.anchor === 'free') {
+ yAcross0 = Math.min(yAcross0, xa.position);
+ yAcross1 = Math.max(yAcross1, xa.position);
+ }
+ yBase = gs.t + (1 - yAcross1) * gs.h;
+ yEndSpike = gs.t + (1 - yAcross0) * gs.h;
}
// Foreground vertical line (to x-axis)
@@ -24005,7 +23998,7 @@ function plainText(s, len) {
});
}
-},{"../../lib":168,"../../lib/events":161,"../../lib/override_cursor":179,"../../lib/svg_text_utils":189,"../../plots/cartesian/axes":212,"../../registry":256,"../color":51,"../dragelement":69,"../drawing":72,"./constants":84,"./helpers":86,"d3":16,"fast-isnumeric":18,"tinycolor2":34}],88:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../lib/events":163,"../../lib/override_cursor":180,"../../lib/svg_text_utils":190,"../../plots/cartesian/axes":213,"../../registry":258,"../color":51,"../dragelement":69,"../drawing":72,"./constants":84,"./helpers":86,"d3":16,"fast-isnumeric":18,"tinycolor2":34}],88:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -24028,52 +24021,7 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts
coerce('hoverlabel.align', opts.align);
};
-},{"../../lib":168}],89:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-module.exports = function(opts, extra) {
- opts = opts || {};
- extra = extra || {};
-
- var descPart = extra.description ? ' ' + extra.description : '';
- var keys = extra.keys || [];
- if(keys.length > 0) {
- var quotedKeys = [];
- for(var i = 0; i < keys.length; i++) {
- quotedKeys[i] = '`' + keys[i] + '`';
- }
- descPart = descPart + 'Finally, the template string has access to ';
- if(keys.length === 1) {
- descPart = 'variable ' + quotedKeys[0];
- } else {
- descPart = 'variables ' + quotedKeys.slice(0, -1).join(', ') + ' and ' + quotedKeys.slice(-1) + '.';
- }
- }
-
- var hovertemplate = {
- valType: 'string',
-
- dflt: '',
- editType: opts.editType || 'none',
-
- };
-
- if(opts.arrayOk !== false) {
- hovertemplate.arrayOk = true;
- }
-
- return hovertemplate;
-};
-
-},{}],90:[function(_dereq_,module,exports){
+},{"../../lib":169}],89:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -24152,7 +24100,7 @@ function castHoverinfo(trace, fullLayout, ptNumber) {
return Lib.castOption(trace, ptNumber, 'hoverinfo', _coerce);
}
-},{"../../lib":168,"../dragelement":69,"./attributes":81,"./calc":82,"./click":83,"./constants":84,"./defaults":85,"./helpers":86,"./hover":87,"./layout_attributes":91,"./layout_defaults":92,"./layout_global_defaults":93,"d3":16}],91:[function(_dereq_,module,exports){
+},{"../../lib":169,"../dragelement":69,"./attributes":81,"./calc":82,"./click":83,"./constants":84,"./defaults":85,"./helpers":86,"./hover":87,"./layout_attributes":90,"./layout_defaults":91,"./layout_global_defaults":92,"d3":16}],90:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -24255,7 +24203,7 @@ module.exports = {
}
};
-},{"../../plots/font_attributes":238,"./constants":84}],92:[function(_dereq_,module,exports){
+},{"../../plots/font_attributes":239,"./constants":84}],91:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -24329,7 +24277,7 @@ function isHoriz(fullData, fullLayout) {
return true;
}
-},{"../../lib":168,"./layout_attributes":91}],93:[function(_dereq_,module,exports){
+},{"../../lib":169,"./layout_attributes":90}],92:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -24352,7 +24300,7 @@ module.exports = function supplyLayoutGlobalDefaults(layoutIn, layoutOut) {
handleHoverLabelDefaults(layoutIn, layoutOut, coerce);
};
-},{"../../lib":168,"./hoverlabel_defaults":88,"./layout_attributes":91}],94:[function(_dereq_,module,exports){
+},{"../../lib":169,"./hoverlabel_defaults":88,"./layout_attributes":90}],93:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -24726,7 +24674,7 @@ module.exports = {
contentDefaults: contentDefaults
};
-},{"../../lib":168,"../../lib/regex":183,"../../plot_api/plot_template":202,"../../plots/cartesian/constants":218,"../../plots/domain":237}],95:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../lib/regex":184,"../../plot_api/plot_template":203,"../../plots/cartesian/constants":219,"../../plots/domain":238}],94:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -24861,7 +24809,7 @@ module.exports = templatedArray('image', {
editType: 'arraydraw'
});
-},{"../../plot_api/plot_template":202,"../../plots/cartesian/constants":218}],96:[function(_dereq_,module,exports){
+},{"../../plot_api/plot_template":203,"../../plots/cartesian/constants":219}],95:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -24942,7 +24890,7 @@ module.exports = function convertCoords(gd, ax, newType, doExtra) {
}
};
-},{"../../lib/to_log_range":191,"fast-isnumeric":18}],97:[function(_dereq_,module,exports){
+},{"../../lib/to_log_range":192,"fast-isnumeric":18}],96:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -25007,7 +24955,7 @@ function imageDefaults(imageIn, imageOut, fullLayout) {
return imageOut;
}
-},{"../../lib":168,"../../plots/array_container_defaults":208,"../../plots/cartesian/axes":212,"./attributes":95}],98:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/array_container_defaults":209,"../../plots/cartesian/axes":213,"./attributes":94}],97:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -25084,49 +25032,54 @@ module.exports = function draw(gd) {
function setImage(d) {
var thisImage = d3.select(this);
- if(this.img && this.img.src === d.source) {
+ if(this._imgSrc === d.source) {
return;
}
thisImage.attr('xmlns', xmlnsNamespaces.svg);
- var imagePromise = new Promise(function(resolve) {
- var img = new Image();
- this.img = img;
+ if(d.source && d.source.slice(0, 5) === 'data:') {
+ thisImage.attr('xlink:href', d.source);
+ this._imgSrc = d.source;
+ } else {
+ var imagePromise = new Promise(function(resolve) {
+ var img = new Image();
+ this.img = img;
- // If not set, a `tainted canvas` error is thrown
- img.setAttribute('crossOrigin', 'anonymous');
- img.onerror = errorHandler;
- img.onload = function() {
- var canvas = document.createElement('canvas');
- canvas.width = this.width;
- canvas.height = this.height;
+ // If not set, a `tainted canvas` error is thrown
+ img.setAttribute('crossOrigin', 'anonymous');
+ img.onerror = errorHandler;
+ img.onload = function() {
+ var canvas = document.createElement('canvas');
+ canvas.width = this.width;
+ canvas.height = this.height;
- var ctx = canvas.getContext('2d');
- ctx.drawImage(this, 0, 0);
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(this, 0, 0);
- var dataURL = canvas.toDataURL('image/png');
+ var dataURL = canvas.toDataURL('image/png');
- thisImage.attr('xlink:href', dataURL);
+ thisImage.attr('xlink:href', dataURL);
- // resolve promise in onload handler instead of on 'load' to support IE11
- // see https://github.com/plotly/plotly.js/issues/1685
- // for more details
- resolve();
- };
+ // resolve promise in onload handler instead of on 'load' to support IE11
+ // see https://github.com/plotly/plotly.js/issues/1685
+ // for more details
+ resolve();
+ };
+ thisImage.on('error', errorHandler);
- thisImage.on('error', errorHandler);
+ img.src = d.source;
+ this._imgSrc = d.source;
- img.src = d.source;
+ function errorHandler() {
+ thisImage.remove();
+ resolve();
+ }
+ }.bind(this));
- function errorHandler() {
- thisImage.remove();
- resolve();
- }
- }.bind(this));
-
- gd._promises.push(imagePromise);
+ gd._promises.push(imagePromise);
+ }
}
function applyAttributes(d) {
@@ -25227,7 +25180,7 @@ module.exports = function draw(gd) {
}
};
-},{"../../constants/xmlns_namespaces":150,"../../plots/cartesian/axes":212,"../drawing":72,"d3":16}],99:[function(_dereq_,module,exports){
+},{"../../constants/xmlns_namespaces":150,"../../plots/cartesian/axes":213,"../drawing":72,"d3":16}],98:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -25251,7 +25204,7 @@ module.exports = {
convertCoords: _dereq_('./convert_coords')
};
-},{"../../plots/cartesian/include_components":222,"./attributes":95,"./convert_coords":96,"./defaults":97,"./draw":98}],100:[function(_dereq_,module,exports){
+},{"../../plots/cartesian/include_components":223,"./attributes":94,"./convert_coords":95,"./defaults":96,"./draw":97}],99:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -25346,7 +25299,6 @@ module.exports = {
valType: 'number',
min: -2,
max: 3,
- dflt: 1.02,
editType: 'legend',
@@ -25363,7 +25315,6 @@ module.exports = {
valType: 'number',
min: -2,
max: 3,
- dflt: 1,
editType: 'legend',
@@ -25371,7 +25322,6 @@ module.exports = {
yanchor: {
valType: 'enumerated',
values: ['auto', 'top', 'middle', 'bottom'],
- dflt: 'auto',
editType: 'legend',
@@ -25393,7 +25343,7 @@ module.exports = {
editType: 'legend'
};
-},{"../../plots/font_attributes":238,"../color/attributes":50}],101:[function(_dereq_,module,exports){
+},{"../../plots/font_attributes":239,"../color/attributes":50}],100:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -25409,10 +25359,15 @@ module.exports = {
scrollBarMinHeight: 20,
scrollBarColor: '#808BA4',
scrollBarMargin: 4,
- textOffsetX: 40
+ scrollBarEnterAttrs: {rx: 20, ry: 3, width: 0, height: 0},
+
+ // number of px between legend symbol and legend text (always in x direction)
+ textGap: 40,
+ // number of px between each legend item (x and/or y direction)
+ itemGap: 5
};
-},{}],102:[function(_dereq_,module,exports){
+},{}],101:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -25439,8 +25394,6 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
var legendReallyHasATrace = false;
var defaultOrder = 'normal';
- var defaultX, defaultY, defaultXAnchor, defaultYAnchor;
-
for(var i = 0; i < fullData.length; i++) {
var trace = fullData[i];
@@ -25497,20 +25450,26 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
coerce('borderwidth');
Lib.coerceFont(coerce, 'font', layoutOut.font);
- coerce('orientation');
- if(containerOut.orientation === 'h') {
- var xaxis = layoutIn.xaxis;
- if(Registry.getComponentMethod('rangeslider', 'isVisible')(xaxis)) {
- defaultX = 0;
- defaultXAnchor = 'left';
+ var orientation = coerce('orientation');
+ var defaultX, defaultY, defaultYAnchor;
+
+ if(orientation === 'h') {
+ defaultX = 0;
+
+ if(Registry.getComponentMethod('rangeslider', 'isVisible')(layoutIn.xaxis)) {
defaultY = 1.1;
defaultYAnchor = 'bottom';
} else {
- defaultX = 0;
- defaultXAnchor = 'left';
+ // maybe use y=1.1 / yanchor=bottom as above
+ // to avoid https://github.com/plotly/plotly.js/issues/1199
+ // in v2
defaultY = -0.1;
defaultYAnchor = 'top';
}
+ } else {
+ defaultX = 1.02;
+ defaultY = 1;
+ defaultYAnchor = 'auto';
}
coerce('traceorder', defaultOrder);
@@ -25522,14 +25481,14 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
coerce('itemdoubleclick');
coerce('x', defaultX);
- coerce('xanchor', defaultXAnchor);
+ coerce('xanchor');
coerce('y', defaultY);
coerce('yanchor', defaultYAnchor);
coerce('valign');
Lib.noneOrAll(containerIn, containerOut, ['x', 'y']);
};
-},{"../../lib":168,"../../plot_api/plot_template":202,"../../plots/layout_attributes":242,"../../registry":256,"./attributes":100,"./helpers":106}],103:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plot_api/plot_template":203,"../../plots/layout_attributes":243,"../../registry":258,"./attributes":99,"./helpers":105}],102:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -25553,7 +25512,6 @@ var svgTextUtils = _dereq_('../../lib/svg_text_utils');
var handleClick = _dereq_('./handle_click');
var constants = _dereq_('./constants');
-var interactConstants = _dereq_('../../constants/interactions');
var alignmentConstants = _dereq_('../../constants/alignment');
var LINE_SPACING = alignmentConstants.LINE_SPACING;
var FROM_TL = alignmentConstants.FROM_TL;
@@ -25563,8 +25521,6 @@ var getLegendData = _dereq_('./get_legend_data');
var style = _dereq_('./style');
var helpers = _dereq_('./helpers');
-var DBLCLICKDELAY = interactConstants.DBLCLICKDELAY;
-
module.exports = function draw(gd) {
var fullLayout = gd._fullLayout;
var clipId = 'legend' + fullLayout._uid;
@@ -25580,26 +25536,11 @@ module.exports = function draw(gd) {
if(!fullLayout.showlegend || !legendData.length) {
fullLayout._infolayer.selectAll('.legend').remove();
fullLayout._topdefs.select('#' + clipId).remove();
-
- Plots.autoMargin(gd, 'legend');
- return;
+ return Plots.autoMargin(gd, 'legend');
}
- var maxLength = 0;
- for(var i = 0; i < legendData.length; i++) {
- for(var j = 0; j < legendData[i].length; j++) {
- var item = legendData[i][j][0];
- var trace = item.trace;
- var isPieLike = Registry.traceIs(trace, 'pie-like');
- var name = isPieLike ? item.label : trace.name;
- maxLength = Math.max(maxLength, name && name.length || 0);
- }
- }
-
- var firstRender = false;
var legend = Lib.ensureSingle(fullLayout._infolayer, 'g', 'legend', function(s) {
s.attr('pointer-events', 'all');
- firstRender = true;
});
var clipPath = Lib.ensureSingleById(fullLayout._topdefs, 'clipPath', clipId, function(s) {
@@ -25609,7 +25550,6 @@ module.exports = function draw(gd) {
var bg = Lib.ensureSingle(legend, 'rect', 'bg', function(s) {
s.attr('shape-rendering', 'crispEdges');
});
-
bg.call(Color.stroke, opts.bordercolor)
.call(Color.fill, opts.bgcolor)
.style('stroke-width', opts.borderwidth + 'px');
@@ -25617,26 +25557,15 @@ module.exports = function draw(gd) {
var scrollBox = Lib.ensureSingle(legend, 'g', 'scrollbox');
var scrollBar = Lib.ensureSingle(legend, 'rect', 'scrollbar', function(s) {
- s.attr({
- rx: 20,
- ry: 3,
- width: 0,
- height: 0
- })
- .call(Color.fill, '#808BA4');
+ s.attr(constants.scrollBarEnterAttrs)
+ .call(Color.fill, constants.scrollBarColor);
});
- var groups = scrollBox.selectAll('g.groups')
- .data(legendData);
-
- groups.enter().append('g')
- .attr('class', 'groups');
-
+ var groups = scrollBox.selectAll('g.groups').data(legendData);
+ groups.enter().append('g').attr('class', 'groups');
groups.exit().remove();
- var traces = groups.selectAll('g.traces')
- .data(Lib.identity);
-
+ var traces = groups.selectAll('g.traces').data(Lib.identity);
traces.enter().append('g').attr('class', 'traces');
traces.exit().remove();
@@ -25648,84 +25577,38 @@ module.exports = function draw(gd) {
return trace.visible === 'legendonly' ? 0.5 : 1;
}
})
- .each(function() {
- d3.select(this)
- .call(drawTexts, gd, maxLength);
- })
+ .each(function() { d3.select(this).call(drawTexts, gd); })
.call(style, gd)
- .each(function() {
- d3.select(this)
- .call(setupTraceToggle, gd);
- });
+ .each(function() { d3.select(this).call(setupTraceToggle, gd); });
- Lib.syncOrAsync([Plots.previousPromises,
+ Lib.syncOrAsync([
+ Plots.previousPromises,
+ function() { return computeLegendDimensions(gd, groups, traces); },
function() {
- if(firstRender) {
- computeLegendDimensions(gd, groups, traces);
- expandMargin(gd);
- }
+ // IF expandMargin return a Promise (which is truthy),
+ // we're under a doAutoMargin redraw, so we don't have to
+ // draw the remaining pieces below
+ if(expandMargin(gd)) return;
- // Position and size the legend
- var lxMin = 0;
- var lxMax = fullLayout.width;
- var lyMin = 0;
- var lyMax = fullLayout.height;
-
- computeLegendDimensions(gd, groups, traces);
-
- if(opts._height > lyMax) {
- // If the legend doesn't fit in the plot area,
- // do not expand the vertical margins.
- expandHorizontalMargin(gd);
- } else {
- expandMargin(gd);
- }
-
- // Scroll section must be executed after repositionLegend.
- // It requires the legend width, height, x and y to position the scrollbox
- // and these values are mutated in repositionLegend.
var gs = fullLayout._size;
- var lx = gs.l + gs.w * opts.x;
- var ly = gs.t + gs.h * (1 - opts.y);
+ var bw = opts.borderwidth;
- if(Lib.isRightAnchor(opts)) {
- lx -= opts._width;
- } else if(Lib.isCenterAnchor(opts)) {
- lx -= opts._width / 2;
- }
+ var lx = gs.l + gs.w * opts.x - FROM_TL[getXanchor(opts)] * opts._width;
+ var ly = gs.t + gs.h * (1 - opts.y) - FROM_TL[getYanchor(opts)] * opts._effHeight;
- if(Lib.isBottomAnchor(opts)) {
- ly -= opts._height;
- } else if(Lib.isMiddleAnchor(opts)) {
- ly -= opts._height / 2;
- }
+ if(fullLayout.margin.autoexpand) {
+ var lx0 = lx;
+ var ly0 = ly;
- // Make sure the legend left and right sides are visible
- var legendWidth = opts._width;
- var legendWidthMax = gs.w;
+ lx = Lib.constrain(lx, 0, fullLayout.width - opts._width);
+ ly = Lib.constrain(ly, 0, fullLayout.height - opts._effHeight);
- if(legendWidth > legendWidthMax) {
- lx = gs.l;
- legendWidth = legendWidthMax;
- } else {
- if(lx + legendWidth > lxMax) lx = lxMax - legendWidth;
- if(lx < lxMin) lx = lxMin;
- legendWidth = Math.min(lxMax - lx, opts._width);
- }
-
- // Make sure the legend top and bottom are visible
- // (legends with a scroll bar are not allowed to stretch beyond the extended
- // margins)
- var legendHeight = opts._height;
- var legendHeightMax = gs.h;
-
- if(legendHeight > legendHeightMax) {
- ly = gs.t;
- legendHeight = legendHeightMax;
- } else {
- if(ly + legendHeight > lyMax) ly = lyMax - legendHeight;
- if(ly < lyMin) ly = lyMin;
- legendHeight = Math.min(lyMax - ly, opts._height);
+ if(lx !== lx0) {
+ Lib.log('Constrain legend.x to make legend fit inside graph');
+ }
+ if(ly !== ly0) {
+ Lib.log('Constrain legend.y to make legend fit inside graph');
+ }
}
// Set size and position of all the elements that make up a legend:
@@ -25736,22 +25619,22 @@ module.exports = function draw(gd) {
scrollBar.on('.drag', null);
legend.on('wheel', null);
- if(opts._height <= legendHeight || gd._context.staticPlot) {
+ if(opts._height <= opts._maxHeight || gd._context.staticPlot) {
// if scrollbar should not be shown.
bg.attr({
- width: legendWidth - opts.borderwidth,
- height: legendHeight - opts.borderwidth,
- x: opts.borderwidth / 2,
- y: opts.borderwidth / 2
+ width: opts._width - bw,
+ height: opts._effHeight - bw,
+ x: bw / 2,
+ y: bw / 2
});
Drawing.setTranslate(scrollBox, 0, 0);
clipPath.select('rect').attr({
- width: legendWidth - 2 * opts.borderwidth,
- height: legendHeight - 2 * opts.borderwidth,
- x: opts.borderwidth,
- y: opts.borderwidth
+ width: opts._width - 2 * bw,
+ height: opts._effHeight - 2 * bw,
+ x: bw,
+ y: bw
});
Drawing.setClipUrl(scrollBox, clipId, gd);
@@ -25760,11 +25643,11 @@ module.exports = function draw(gd) {
delete opts._scrollY;
} else {
var scrollBarHeight = Math.max(constants.scrollBarMinHeight,
- legendHeight * legendHeight / opts._height);
- var scrollBarYMax = legendHeight -
+ opts._effHeight * opts._effHeight / opts._height);
+ var scrollBarYMax = opts._effHeight -
scrollBarHeight -
2 * constants.scrollBarMargin;
- var scrollBoxYMax = opts._height - legendHeight;
+ var scrollBoxYMax = opts._height - opts._effHeight;
var scrollRatio = scrollBarYMax / scrollBoxYMax;
var scrollBoxY = Math.min(opts._scrollY || 0, scrollBoxYMax);
@@ -25772,33 +25655,34 @@ module.exports = function draw(gd) {
// increase the background and clip-path width
// by the scrollbar width and margin
bg.attr({
- width: legendWidth -
- 2 * opts.borderwidth +
+ width: opts._width -
+ 2 * bw +
constants.scrollBarWidth +
constants.scrollBarMargin,
- height: legendHeight - opts.borderwidth,
- x: opts.borderwidth / 2,
- y: opts.borderwidth / 2
+ height: opts._effHeight - bw,
+ x: bw / 2,
+ y: bw / 2
});
clipPath.select('rect').attr({
- width: legendWidth -
- 2 * opts.borderwidth +
+ width: opts._width -
+ 2 * bw +
constants.scrollBarWidth +
constants.scrollBarMargin,
- height: legendHeight - 2 * opts.borderwidth,
- x: opts.borderwidth,
- y: opts.borderwidth + scrollBoxY
+ height: opts._effHeight - 2 * bw,
+ x: bw,
+ y: bw + scrollBoxY
});
Drawing.setClipUrl(scrollBox, clipId, gd);
scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio);
+ // scroll legend by mousewheel or touchpad swipe up/down
legend.on('wheel', function() {
scrollBoxY = Lib.constrain(
opts._scrollY +
- d3.event.deltaY / scrollBarYMax * scrollBoxYMax,
+ ((d3.event.deltaY / scrollBarYMax) * scrollBoxYMax),
0, scrollBoxYMax);
scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio);
if(scrollBoxY !== 0 && scrollBoxY !== scrollBoxYMax) {
@@ -25806,41 +25690,74 @@ module.exports = function draw(gd) {
}
});
- var eventY0, scrollBoxY0;
+ var eventY0, eventY1, scrollBoxY0;
- var drag = d3.behavior.drag()
+ var getScrollBarDragY = function(scrollBoxY0, eventY0, eventY1) {
+ var y = ((eventY1 - eventY0) / scrollRatio) + scrollBoxY0;
+ return Lib.constrain(y, 0, scrollBoxYMax);
+ };
+
+ var getNaturalDragY = function(scrollBoxY0, eventY0, eventY1) {
+ var y = ((eventY0 - eventY1) / scrollRatio) + scrollBoxY0;
+ return Lib.constrain(y, 0, scrollBoxYMax);
+ };
+
+ // scroll legend by dragging scrollBAR
+ var scrollBarDrag = d3.behavior.drag()
.on('dragstart', function() {
- eventY0 = d3.event.sourceEvent.clientY;
+ var e = d3.event.sourceEvent;
+ if(e.type === 'touchstart') {
+ eventY0 = e.changedTouches[0].clientY;
+ } else {
+ eventY0 = e.clientY;
+ }
scrollBoxY0 = scrollBoxY;
})
.on('drag', function() {
var e = d3.event.sourceEvent;
if(e.buttons === 2 || e.ctrlKey) return;
-
- scrollBoxY = Lib.constrain(
- (e.clientY - eventY0) / scrollRatio + scrollBoxY0,
- 0, scrollBoxYMax);
+ if(e.type === 'touchmove') {
+ eventY1 = e.changedTouches[0].clientY;
+ } else {
+ eventY1 = e.clientY;
+ }
+ scrollBoxY = getScrollBarDragY(scrollBoxY0, eventY0, eventY1);
scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio);
});
+ scrollBar.call(scrollBarDrag);
- scrollBar.call(drag);
+ // scroll legend by touch-dragging scrollBOX
+ var scrollBoxTouchDrag = d3.behavior.drag()
+ .on('dragstart', function() {
+ var e = d3.event.sourceEvent;
+ if(e.type === 'touchstart') {
+ eventY0 = e.changedTouches[0].clientY;
+ scrollBoxY0 = scrollBoxY;
+ }
+ })
+ .on('drag', function() {
+ var e = d3.event.sourceEvent;
+ if(e.type === 'touchmove') {
+ eventY1 = e.changedTouches[0].clientY;
+ scrollBoxY = getNaturalDragY(scrollBoxY0, eventY0, eventY1);
+ scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio);
+ }
+ });
+ scrollBox.call(scrollBoxTouchDrag);
}
-
function scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio) {
opts._scrollY = gd._fullLayout.legend._scrollY = scrollBoxY;
Drawing.setTranslate(scrollBox, 0, -scrollBoxY);
Drawing.setRect(
scrollBar,
- legendWidth,
+ opts._width,
constants.scrollBarMargin + scrollBoxY * scrollRatio,
constants.scrollBarWidth,
scrollBarHeight
);
- clipPath.select('rect').attr({
- y: opts.borderwidth + scrollBoxY
- });
+ clipPath.select('rect').attr('y', bw + scrollBoxY);
}
if(gd._context.edits.legendPosition) {
@@ -25853,7 +25770,6 @@ module.exports = function draw(gd) {
gd: gd,
prepFn: function() {
var transform = Drawing.getTranslate(legend);
-
x0 = transform.x;
y0 = transform.y;
},
@@ -25890,7 +25806,6 @@ module.exports = function draw(gd) {
function clickOrDoubleClick(gd, legend, legendItem, numClicks, evt) {
var trace = legendItem.data()[0][0].trace;
-
var evtData = {
event: evt,
node: legendItem.node(),
@@ -25917,7 +25832,7 @@ function clickOrDoubleClick(gd, legend, legendItem, numClicks, evt) {
if(numClicks === 1) {
legend._clickTimeout = setTimeout(function() {
handleClick(legendItem, gd, numClicks);
- }, DBLCLICKDELAY);
+ }, gd._context.doubleClickDelay);
} else if(numClicks === 2) {
if(legend._clickTimeout) clearTimeout(legend._clickTimeout);
gd._legendMouseDownTime = 0;
@@ -25927,13 +25842,15 @@ function clickOrDoubleClick(gd, legend, legendItem, numClicks, evt) {
}
}
-function drawTexts(g, gd, maxLength) {
+function drawTexts(g, gd) {
var legendItem = g.data()[0][0];
var fullLayout = gd._fullLayout;
+ var opts = fullLayout.legend;
var trace = legendItem.trace;
var isPieLike = Registry.traceIs(trace, 'pie-like');
var traceIndex = trace.index;
var isEditable = gd._context.edits.legendText && !isPieLike;
+ var maxNameLength = opts._maxNameLength;
var name = isPieLike ? legendItem.label : trace.name;
if(trace._meta) {
@@ -25945,9 +25862,9 @@ function drawTexts(g, gd, maxLength) {
textEl.attr('text-anchor', 'start')
.classed('user-select-none', true)
.call(Drawing.font, fullLayout.legend.font)
- .text(isEditable ? ensureLength(name, maxLength) : name);
+ .text(isEditable ? ensureLength(name, maxNameLength) : name);
- svgTextUtils.positionText(textEl, constants.textOffsetX, 0);
+ svgTextUtils.positionText(textEl, constants.textGap, 0);
function textLayout(s) {
svgTextUtils.convertToTspans(s, gd, function() {
@@ -25959,7 +25876,7 @@ function drawTexts(g, gd, maxLength) {
textEl.call(svgTextUtils.makeEditable, {gd: gd, text: name})
.call(textLayout)
.on('edit', function(newName) {
- this.text(ensureLength(newName, maxLength))
+ this.text(ensureLength(newName, maxNameLength))
.call(textLayout);
var fullInput = legendItem.trace._fullInput || {};
@@ -26001,6 +25918,7 @@ function ensureLength(str, maxLength) {
}
function setupTraceToggle(g, gd) {
+ var doubleClickDelay = gd._context.doubleClickDelay;
var newMouseDownTime;
var numClicks = 1;
@@ -26012,7 +25930,7 @@ function setupTraceToggle(g, gd) {
traceToggle.on('mousedown', function() {
newMouseDownTime = (new Date()).getTime();
- if(newMouseDownTime - gd._legendMouseDownTime < DBLCLICKDELAY) {
+ if(newMouseDownTime - gd._legendMouseDownTime < doubleClickDelay) {
// in a click train
numClicks += 1;
} else {
@@ -26025,7 +25943,7 @@ function setupTraceToggle(g, gd) {
if(gd._dragged || gd._editing) return;
var legend = gd._fullLayout.legend;
- if((new Date()).getTime() - gd._legendMouseDownTime > DBLCLICKDELAY) {
+ if((new Date()).getTime() - gd._legendMouseDownTime > doubleClickDelay) {
numClicks = Math.max(numClicks - 1, 1);
}
@@ -26065,7 +25983,7 @@ function computeTextDimensions(g, gd) {
// approximation to height offset to center the font
// to avoid getBoundingClientRect
var textY = lineHeight * (0.3 + (1 - textLines) / 2);
- svgTextUtils.positionText(text, constants.textOffsetX, textY);
+ svgTextUtils.positionText(text, constants.textGap, textY);
}
legendItem.lineHeight = lineHeight;
@@ -26073,243 +25991,202 @@ function computeTextDimensions(g, gd) {
legendItem.width = width;
}
+/*
+ * Computes in fullLayout.legend:
+ *
+ * - _height: legend height including items past scrollbox height
+ * - _maxHeight: maximum legend height before scrollbox is required
+ * - _effHeight: legend height w/ or w/o scrollbox
+ *
+ * - _width: legend width
+ * - _maxWidth (for orientation:h only): maximum width before starting new row
+ */
function computeLegendDimensions(gd, groups, traces) {
var fullLayout = gd._fullLayout;
var opts = fullLayout.legend;
- var borderwidth = opts.borderwidth;
+ var gs = fullLayout._size;
+ var isVertical = helpers.isVertical(opts);
var isGrouped = helpers.isGrouped(opts);
- var extraWidth = 0;
+ var bw = opts.borderwidth;
+ var bw2 = 2 * bw;
+ var textGap = constants.textGap;
+ var itemGap = constants.itemGap;
+ var endPad = 2 * (bw + itemGap);
- var traceGap = 5;
+ var yanchor = getYanchor(opts);
+ var isBelowPlotArea = opts.y < 0 || (opts.y === 0 && yanchor === 'top');
+ var isAbovePlotArea = opts.y > 1 || (opts.y === 1 && yanchor === 'bottom');
+ // - if below/above plot area, give it the maximum potential margin-push value
+ // - otherwise, extend the height of the plot area
+ opts._maxHeight = Math.max(
+ (isBelowPlotArea || isAbovePlotArea) ? fullLayout.height / 2 : gs.h,
+ 30
+ );
+
+ var toggleRectWidth = 0;
opts._width = 0;
opts._height = 0;
- if(helpers.isVertical(opts)) {
+ if(isVertical) {
+ traces.each(function(d) {
+ var h = d[0].height;
+ Drawing.setTranslate(this, bw, itemGap + bw + opts._height + h / 2);
+ opts._height += h;
+ opts._width = Math.max(opts._width, d[0].width);
+ });
+
+ toggleRectWidth = textGap + opts._width;
+ opts._width += itemGap + textGap + bw2;
+ opts._height += endPad;
+
if(isGrouped) {
groups.each(function(d, i) {
Drawing.setTranslate(this, 0, i * opts.tracegroupgap);
});
- }
-
- traces.each(function(d) {
- var legendItem = d[0];
- var textHeight = legendItem.height;
- var textWidth = legendItem.width;
-
- Drawing.setTranslate(this,
- borderwidth,
- (5 + borderwidth + opts._height + textHeight / 2));
-
- opts._height += textHeight;
- opts._width = Math.max(opts._width, textWidth);
- });
-
- opts._width += 45 + borderwidth * 2;
- opts._height += 10 + borderwidth * 2;
-
- if(isGrouped) {
opts._height += (opts._lgroupsLength - 1) * opts.tracegroupgap;
}
-
- extraWidth = 40;
- } else if(isGrouped) {
- var maxHeight = 0;
- var maxWidth = 0;
- var groupData = groups.data();
-
- var maxItems = 0;
-
- var i;
- for(i = 0; i < groupData.length; i++) {
- var group = groupData[i];
- var groupWidths = group.map(function(legendItemArray) {
- return legendItemArray[0].width;
- });
-
- var groupWidth = Lib.aggNums(Math.max, null, groupWidths);
- var groupHeight = group.reduce(function(a, b) {
- return a + b[0].height;
- }, 0);
-
- maxWidth = Math.max(maxWidth, groupWidth);
- maxHeight = Math.max(maxHeight, groupHeight);
- maxItems = Math.max(maxItems, group.length);
- }
-
- maxWidth += traceGap;
- maxWidth += 40;
-
- var groupXOffsets = [opts._width];
- var groupYOffsets = [];
- var rowNum = 0;
- for(i = 0; i < groupData.length; i++) {
- if(fullLayout._size.w < (borderwidth + opts._width + traceGap + maxWidth)) {
- groupXOffsets[groupXOffsets.length - 1] = groupXOffsets[0];
- opts._width = maxWidth;
- rowNum++;
- } else {
- opts._width += maxWidth + borderwidth;
- }
-
- var rowYOffset = (rowNum * maxHeight);
- rowYOffset += rowNum > 0 ? opts.tracegroupgap : 0;
-
- groupYOffsets.push(rowYOffset);
- groupXOffsets.push(opts._width);
- }
-
- groups.each(function(d, i) {
- Drawing.setTranslate(this, groupXOffsets[i], groupYOffsets[i]);
- });
-
- groups.each(function() {
- var group = d3.select(this);
- var groupTraces = group.selectAll('g.traces');
- var groupHeight = 0;
-
- groupTraces.each(function(d) {
- var legendItem = d[0];
- var textHeight = legendItem.height;
-
- Drawing.setTranslate(this,
- 0,
- (5 + borderwidth + groupHeight + textHeight / 2));
-
- groupHeight += textHeight;
- });
- });
-
- var maxYLegend = groupYOffsets[groupYOffsets.length - 1] + maxHeight;
- opts._height = 10 + (borderwidth * 2) + maxYLegend;
-
- var maxOffset = Math.max.apply(null, groupXOffsets);
- opts._width = maxOffset + maxWidth + 40;
- opts._width += borderwidth * 2;
} else {
- var rowHeight = 0;
- var maxTraceHeight = 0;
- var maxTraceWidth = 0;
- var offsetX = 0;
- var fullTracesWidth = 0;
+ var xanchor = getXanchor(opts);
+ var isLeftOfPlotArea = opts.x < 0 || (opts.x === 0 && xanchor === 'right');
+ var isRightOfPlotArea = opts.x > 1 || (opts.x === 1 && xanchor === 'left');
+ var isBeyondPlotAreaY = isAbovePlotArea || isBelowPlotArea;
+ var hw = fullLayout.width / 2;
- // calculate largest width for traces and use for width of all legend items
+ // - if placed within x-margins, extend the width of the plot area
+ // - else if below/above plot area and anchored in the margin, extend to opposite margin,
+ // - otherwise give it the maximum potential margin-push value
+ opts._maxWidth = Math.max(
+ isLeftOfPlotArea ? ((isBeyondPlotAreaY && xanchor === 'left') ? gs.l + gs.w : hw) :
+ isRightOfPlotArea ? ((isBeyondPlotAreaY && xanchor === 'right') ? gs.r + gs.w : hw) :
+ gs.w,
+ 2 * textGap);
+ var maxItemWidth = 0;
+ var combinedItemWidth = 0;
traces.each(function(d) {
- maxTraceWidth = Math.max(40 + d[0].width, maxTraceWidth);
- fullTracesWidth += 40 + d[0].width + traceGap;
+ var w = d[0].width + textGap;
+ maxItemWidth = Math.max(maxItemWidth, w);
+ combinedItemWidth += w;
});
- // check if legend fits in one row
- var oneRowLegend = fullLayout._size.w > borderwidth + fullTracesWidth - traceGap;
+ toggleRectWidth = null;
+ var maxRowWidth = 0;
- traces.each(function(d) {
- var legendItem = d[0];
- var traceWidth = oneRowLegend ? 40 + d[0].width : maxTraceWidth;
+ if(isGrouped) {
+ var maxGroupHeightInRow = 0;
+ var groupOffsetX = 0;
+ var groupOffsetY = 0;
+ groups.each(function() {
+ var maxWidthInGroup = 0;
+ var offsetY = 0;
+ d3.select(this).selectAll('g.traces').each(function(d) {
+ var h = d[0].height;
+ Drawing.setTranslate(this, 0, itemGap + bw + h / 2 + offsetY);
+ offsetY += h;
+ maxWidthInGroup = Math.max(maxWidthInGroup, textGap + d[0].width);
+ });
+ maxGroupHeightInRow = Math.max(maxGroupHeightInRow, offsetY);
- if((borderwidth + offsetX + traceGap + traceWidth) > fullLayout._size.w) {
- offsetX = 0;
- rowHeight += maxTraceHeight;
- opts._height += maxTraceHeight;
- // reset for next row
- maxTraceHeight = 0;
- }
+ var next = maxWidthInGroup + itemGap;
- Drawing.setTranslate(this,
- (borderwidth + offsetX),
- (5 + borderwidth + legendItem.height / 2) + rowHeight);
+ if((next + bw + groupOffsetX) > opts._maxWidth) {
+ maxRowWidth = Math.max(maxRowWidth, groupOffsetX);
+ groupOffsetX = 0;
+ groupOffsetY += maxGroupHeightInRow + opts.tracegroupgap;
+ maxGroupHeightInRow = offsetY;
+ }
- opts._width += traceGap + traceWidth;
+ Drawing.setTranslate(this, groupOffsetX, groupOffsetY);
- // keep track of tallest trace in group
- offsetX += traceGap + traceWidth;
- maxTraceHeight = Math.max(legendItem.height, maxTraceHeight);
- });
+ groupOffsetX += next;
+ });
- if(oneRowLegend) {
- opts._height = maxTraceHeight;
+ opts._width = Math.max(maxRowWidth, groupOffsetX) + bw;
+ opts._height = groupOffsetY + maxGroupHeightInRow + endPad;
} else {
- opts._height += maxTraceHeight;
- }
+ var nTraces = traces.size();
+ var oneRowLegend = (combinedItemWidth + bw2 + (nTraces - 1) * itemGap) < opts._maxWidth;
- opts._width += borderwidth * 2;
- opts._height += 10 + borderwidth * 2;
+ var maxItemHeightInRow = 0;
+ var offsetX = 0;
+ var offsetY = 0;
+ var rowWidth = 0;
+ traces.each(function(d) {
+ var h = d[0].height;
+ var w = textGap + d[0].width;
+ var next = (oneRowLegend ? w : maxItemWidth) + itemGap;
+
+ if((next + bw + offsetX) > opts._maxWidth) {
+ maxRowWidth = Math.max(maxRowWidth, rowWidth);
+ offsetX = 0;
+ offsetY += maxItemHeightInRow;
+ opts._height += maxItemHeightInRow;
+ maxItemHeightInRow = 0;
+ }
+
+ Drawing.setTranslate(this, bw + offsetX, itemGap + bw + h / 2 + offsetY);
+
+ rowWidth = offsetX + w + itemGap;
+ offsetX += next;
+ maxItemHeightInRow = Math.max(maxItemHeightInRow, h);
+ });
+
+ if(oneRowLegend) {
+ opts._width = offsetX + bw2;
+ opts._height = maxItemHeightInRow + endPad;
+ } else {
+ opts._width = Math.max(maxRowWidth, rowWidth) + bw2;
+ opts._height += maxItemHeightInRow + endPad;
+ }
+ }
}
- // make sure we're only getting full pixels
opts._width = Math.ceil(opts._width);
opts._height = Math.ceil(opts._height);
- var isEditable = (
- gd._context.edits.legendText ||
- gd._context.edits.legendPosition
- );
+ opts._effHeight = Math.min(opts._height, opts._maxHeight);
+ var edits = gd._context.edits;
+ var isEditable = edits.legendText || edits.legendPosition;
traces.each(function(d) {
- var legendItem = d[0];
- var bg = d3.select(this).select('.legendtoggle');
-
- Drawing.setRect(bg,
- 0,
- -legendItem.height / 2,
- (isEditable ? 0 : opts._width) + extraWidth,
- legendItem.height
- );
+ var traceToggle = d3.select(this).select('.legendtoggle');
+ var h = d[0].height;
+ var w = isEditable ? textGap : (toggleRectWidth || (textGap + d[0].width));
+ if(!isVertical) w += itemGap / 2;
+ Drawing.setRect(traceToggle, 0, -h / 2, w, h);
});
}
function expandMargin(gd) {
var fullLayout = gd._fullLayout;
var opts = fullLayout.legend;
+ var xanchor = getXanchor(opts);
+ var yanchor = getYanchor(opts);
- var xanchor = 'left';
- if(Lib.isRightAnchor(opts)) {
- xanchor = 'right';
- } else if(Lib.isCenterAnchor(opts)) {
- xanchor = 'center';
- }
-
- var yanchor = 'top';
- if(Lib.isBottomAnchor(opts)) {
- yanchor = 'bottom';
- } else if(Lib.isMiddleAnchor(opts)) {
- yanchor = 'middle';
- }
-
- // lastly check if the margin auto-expand has changed
- Plots.autoMargin(gd, 'legend', {
+ return Plots.autoMargin(gd, 'legend', {
x: opts.x,
y: opts.y,
l: opts._width * (FROM_TL[xanchor]),
r: opts._width * (FROM_BR[xanchor]),
- b: opts._height * (FROM_BR[yanchor]),
- t: opts._height * (FROM_TL[yanchor])
+ b: opts._effHeight * (FROM_BR[yanchor]),
+ t: opts._effHeight * (FROM_TL[yanchor])
});
}
-function expandHorizontalMargin(gd) {
- var fullLayout = gd._fullLayout;
- var opts = fullLayout.legend;
-
- var xanchor = 'left';
- if(Lib.isRightAnchor(opts)) {
- xanchor = 'right';
- } else if(Lib.isCenterAnchor(opts)) {
- xanchor = 'center';
- }
-
- // lastly check if the margin auto-expand has changed
- Plots.autoMargin(gd, 'legend', {
- x: opts.x,
- y: 0.5,
- l: opts._width * (FROM_TL[xanchor]),
- r: opts._width * (FROM_BR[xanchor]),
- b: 0,
- t: 0
- });
+function getXanchor(opts) {
+ return Lib.isRightAnchor(opts) ? 'right' :
+ Lib.isCenterAnchor(opts) ? 'center' :
+ 'left';
}
-},{"../../constants/alignment":146,"../../constants/interactions":148,"../../lib":168,"../../lib/events":161,"../../lib/svg_text_utils":189,"../../plots/plots":244,"../../registry":256,"../color":51,"../dragelement":69,"../drawing":72,"./constants":101,"./get_legend_data":104,"./handle_click":105,"./helpers":106,"./style":108,"d3":16}],104:[function(_dereq_,module,exports){
+function getYanchor(opts) {
+ return Lib.isBottomAnchor(opts) ? 'bottom' :
+ Lib.isMiddleAnchor(opts) ? 'middle' :
+ 'top';
+}
+
+},{"../../constants/alignment":145,"../../lib":169,"../../lib/events":163,"../../lib/svg_text_utils":190,"../../plots/plots":245,"../../registry":258,"../color":51,"../dragelement":69,"../drawing":72,"./constants":100,"./get_legend_data":103,"./handle_click":104,"./helpers":105,"./style":107,"d3":16}],103:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -26329,13 +26206,14 @@ module.exports = function getLegendData(calcdata, opts) {
var hasOneNonBlankGroup = false;
var slicesShown = {};
var lgroupi = 0;
+ var maxNameLength = 0;
var i, j;
function addOneItem(legendGroup, legendItem) {
// each '' legend group is treated as a separate group
if(legendGroup === '' || !helpers.isGrouped(opts)) {
- var uniqueGroup = '~~i' + lgroupi; // TODO: check this against fullData legendgroups?
-
+ // TODO: check this against fullData legendgroups?
+ var uniqueGroup = '~~i' + lgroupi;
lgroups.push(uniqueGroup);
lgroupToTraces[uniqueGroup] = [[legendItem]];
lgroupi++;
@@ -26343,7 +26221,9 @@ module.exports = function getLegendData(calcdata, opts) {
lgroups.push(legendGroup);
hasOneNonBlankGroup = true;
lgroupToTraces[legendGroup] = [[legendItem]];
- } else lgroupToTraces[legendGroup].push([legendItem]);
+ } else {
+ lgroupToTraces[legendGroup].push([legendItem]);
+ }
}
// build an { legendgroup: [cd0, cd0], ... } object
@@ -26371,9 +26251,13 @@ module.exports = function getLegendData(calcdata, opts) {
});
slicesShown[lgroup][labelj] = true;
+ maxNameLength = Math.max(maxNameLength, (labelj || '').length);
}
}
- } else addOneItem(lgroup, cd0);
+ } else {
+ addOneItem(lgroup, cd0);
+ maxNameLength = Math.max(maxNameLength, (trace.name || '').length);
+ }
}
// won't draw a legend in this case
@@ -26402,12 +26286,15 @@ module.exports = function getLegendData(calcdata, opts) {
lgroupsLength = 1;
}
- // needed in repositionLegend
+ // number of legend groups - needed in legend/draw.js
opts._lgroupsLength = lgroupsLength;
+ // maximum name/label length - needed in legend/draw.js
+ opts._maxNameLength = maxNameLength;
+
return legendData;
};
-},{"../../registry":256,"./helpers":106}],105:[function(_dereq_,module,exports){
+},{"../../registry":258,"./helpers":105}],104:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -26643,7 +26530,7 @@ module.exports = function handleClick(g, gd, numClicks) {
}
};
-},{"../../lib":168,"../../registry":256}],106:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../registry":258}],105:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -26667,7 +26554,7 @@ exports.isReversed = function isReversed(legendLayout) {
return (legendLayout.traceorder || '').indexOf('reversed') !== -1;
};
-},{}],107:[function(_dereq_,module,exports){
+},{}],106:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -26691,7 +26578,7 @@ module.exports = {
style: _dereq_('./style')
};
-},{"./attributes":100,"./defaults":102,"./draw":103,"./style":108}],108:[function(_dereq_,module,exports){
+},{"./attributes":99,"./defaults":101,"./draw":102,"./style":107}],107:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -26708,6 +26595,7 @@ var Registry = _dereq_('../../registry');
var Lib = _dereq_('../../lib');
var Drawing = _dereq_('../drawing');
var Color = _dereq_('../color');
+var extractOpts = _dereq_('../colorscale/helpers').extractOpts;
var subTypes = _dereq_('../../traces/scatter/subtypes');
var stylePie = _dereq_('../../traces/pie/style_one');
@@ -26724,7 +26612,7 @@ module.exports = function style(s, gd) {
var legend = fullLayout.legend;
var constantItemSizing = legend.itemsizing === 'constant';
- function boundLineWidth(mlw, cont, max, cst) {
+ var boundLineWidth = function(mlw, cont, max, cst) {
var v;
if(mlw + 1) {
v = mlw;
@@ -26734,7 +26622,7 @@ module.exports = function style(s, gd) {
return 0;
}
return constantItemSizing ? cst : Math.min(v, max);
- }
+ };
s.each(function(d) {
var traceGroup = d3.select(this);
@@ -26798,6 +26686,29 @@ module.exports = function style(s, gd) {
var showGradientFill = false;
var dMod, tMod;
+ var cOpts = extractOpts(trace);
+ var colorscale = cOpts.colorscale;
+ var reversescale = cOpts.reversescale;
+
+ var fillGradient = function(s) {
+ if(s.size()) {
+ var gradientID = 'legendfill-' + trace.uid;
+ Drawing.gradient(s, gd, gradientID,
+ getGradientDirection(reversescale),
+ colorscale, 'fill');
+ }
+ };
+
+ var lineGradient = function(s) {
+ if(s.size()) {
+ var gradientID = 'legendline-' + trace.uid;
+ Drawing.lineGroupStyle(s);
+ Drawing.gradient(s, gd, gradientID,
+ getGradientDirection(reversescale),
+ colorscale, 'stroke');
+ }
+ };
+
if(contours) {
var coloring = contours.coloring;
@@ -26852,23 +26763,6 @@ module.exports = function style(s, gd) {
// This issue (and workaround) exist across (Mac) Chrome, FF, and Safari
line.attr('d', pathStart + (showGradientLine ? 'l30,0.0001' : 'h30'))
.call(showLine ? Drawing.lineGroupStyle : lineGradient);
-
- function fillGradient(s) {
- if(s.size()) {
- var gradientID = 'legendfill-' + trace.uid;
- Drawing.gradient(s, gd, gradientID, 'horizontalreversed',
- trace.colorscale, 'fill');
- }
- }
-
- function lineGradient(s) {
- if(s.size()) {
- var gradientID = 'legendline-' + trace.uid;
- Drawing.lineGroupStyle(s);
- Drawing.gradient(s, gd, gradientID, 'horizontalreversed',
- trace.colorscale, 'stroke');
- }
- }
}
function stylePoints(d) {
@@ -26942,6 +26836,9 @@ module.exports = function style(s, gd) {
// always show legend items in base state
tMod.selectedpoints = null;
+
+ // never show texttemplate
+ tMod.texttemplate = null;
}
var ptgroup = d3.select(this).select('g.legendpoints');
@@ -26972,7 +26869,7 @@ module.exports = function style(s, gd) {
var trace = d[0].trace;
var ptsData = [];
- if(trace.type === 'waterfall' && trace.visible) {
+ if(trace.visible && trace.type === 'waterfall') {
ptsData = d[0].hasTotals ?
[['increasing', 'M-6,-6V6H0Z'], ['totals', 'M6,6H0L-6,-6H-0Z'], ['decreasing', 'M6,6V-6H0Z']] :
[['increasing', 'M-6,-6V6H6Z'], ['decreasing', 'M6,6V-6H-6Z']];
@@ -27015,7 +26912,7 @@ module.exports = function style(s, gd) {
var markerLine = marker.line || {};
var isVisible = (!desiredType) ? Registry.traceIs(trace, 'bar') :
- (trace.type === desiredType && trace.visible);
+ (trace.visible && trace.type === desiredType);
var barpath = d3.select(lThis).select('g.legendpoints')
.selectAll('path.legend' + desiredType)
@@ -27042,7 +26939,7 @@ module.exports = function style(s, gd) {
var pts = d3.select(this).select('g.legendpoints')
.selectAll('path.legendbox')
- .data(Registry.traceIs(trace, 'box-violin') && trace.visible ? [d] : []);
+ .data(trace.visible && Registry.traceIs(trace, 'box-violin') ? [d] : []);
pts.enter().append('path').classed('legendbox', true)
// if we want the median bar, prepend M6,0H-6
.attr('d', 'M6,6H-6V-6H6Z')
@@ -27080,7 +26977,7 @@ module.exports = function style(s, gd) {
var pts = d3.select(this).select('g.legendpoints')
.selectAll('path.legendcandle')
- .data(trace.type === 'candlestick' && trace.visible ? [d, d] : []);
+ .data(trace.visible && trace.type === 'candlestick' ? [d, d] : []);
pts.enter().append('path').classed('legendcandle', true)
.attr('d', function(_, i) {
if(i) return 'M-15,0H-8M-8,6V-6H8Z'; // increasing
@@ -27107,7 +27004,7 @@ module.exports = function style(s, gd) {
var pts = d3.select(this).select('g.legendpoints')
.selectAll('path.legendohlc')
- .data(trace.type === 'ohlc' && trace.visible ? [d, d] : []);
+ .data(trace.visible && trace.type === 'ohlc' ? [d, d] : []);
pts.enter().append('path').classed('legendohlc', true)
.attr('d', function(_, i) {
if(i) return 'M-15,0H0M-8,-6V0'; // increasing
@@ -27142,7 +27039,7 @@ module.exports = function style(s, gd) {
var trace = d0.trace;
var isVisible = (!desiredType) ? Registry.traceIs(trace, desiredType) :
- (trace.type === desiredType && trace.visible);
+ (trace.visible && trace.type === desiredType);
var pts = d3.select(lThis).select('g.legendpoints')
.selectAll('path.legend' + desiredType)
@@ -27167,7 +27064,11 @@ module.exports = function style(s, gd) {
}
};
-},{"../../lib":168,"../../registry":256,"../../traces/pie/helpers":357,"../../traces/pie/style_one":363,"../../traces/scatter/subtypes":388,"../color":51,"../drawing":72,"d3":16}],109:[function(_dereq_,module,exports){
+function getGradientDirection(reversescale) {
+ return reversescale ? 'horizontal' : 'horizontalreversed';
+}
+
+},{"../../lib":169,"../../registry":258,"../../traces/pie/helpers":369,"../../traces/pie/style_one":375,"../../traces/scatter/subtypes":401,"../color":51,"../colorscale/helpers":62,"../drawing":72,"d3":16}],108:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -27182,7 +27083,7 @@ var Registry = _dereq_('../../registry');
var Plots = _dereq_('../../plots/plots');
var axisIds = _dereq_('../../plots/cartesian/axis_ids');
var Lib = _dereq_('../../lib');
-var Icons = _dereq_('../../../build/ploticon');
+var Icons = _dereq_('../../fonts/ploticon');
var _ = Lib._;
@@ -27259,6 +27160,15 @@ modeBarButtons.sendDataToCloud = {
}
};
+modeBarButtons.editInChartStudio = {
+ name: 'editInChartStudio',
+ title: function(gd) { return _(gd, 'Edit in Chart Studio'); },
+ icon: Icons.pencil,
+ click: function(gd) {
+ Plots.sendDataToCloud(gd);
+ }
+};
+
modeBarButtons.zoom2d = {
name: 'zoom2d',
title: function(gd) { return _(gd, 'Zoom'); },
@@ -27360,7 +27270,7 @@ function handleCartesian(gd, ev) {
var fullLayout = gd._fullLayout;
var aobj = {};
var axList = axisIds.list(gd, null, true);
- var allSpikesEnabled = 'on';
+ var allSpikesEnabled = fullLayout._cartesianSpikesEnabled;
var ax, i;
@@ -27375,8 +27285,9 @@ function handleCartesian(gd, ev) {
if(!ax.fixedrange) {
axName = ax._name;
- if(val === 'auto') aobj[axName + '.autorange'] = true;
- else if(val === 'reset') {
+ if(val === 'auto') {
+ aobj[axName + '.autorange'] = true;
+ } else if(val === 'reset') {
if(ax._rangeInitial === undefined) {
aobj[axName + '.autorange'] = true;
} else {
@@ -27384,6 +27295,8 @@ function handleCartesian(gd, ev) {
aobj[axName + '.range[0]'] = rangeInitial[0];
aobj[axName + '.range[1]'] = rangeInitial[1];
}
+
+ // N.B. "reset" also resets showspikes
if(ax._showSpikeInitial !== undefined) {
aobj[axName + '.showspikes'] = ax._showSpikeInitial;
if(allSpikesEnabled === 'on' && !ax._showSpikeInitial) {
@@ -27406,25 +27319,18 @@ function handleCartesian(gd, ev) {
}
}
}
- fullLayout._cartesianSpikesEnabled = allSpikesEnabled;
} else {
// if ALL traces have orientation 'h', 'hovermode': 'x' otherwise: 'y'
if(astr === 'hovermode' && (val === 'x' || val === 'y')) {
val = fullLayout._isHoriz ? 'y' : 'x';
button.setAttribute('data-val', val);
- } else if(astr === 'hovermode' && val === 'closest') {
- for(i = 0; i < axList.length; i++) {
- ax = axList[i];
- if(allSpikesEnabled === 'on' && !ax.showspikes) {
- allSpikesEnabled = 'off';
- }
- }
- fullLayout._cartesianSpikesEnabled = allSpikesEnabled;
}
aobj[astr] = val;
}
+ fullLayout._cartesianSpikesEnabled = allSpikesEnabled;
+
Registry.call('_guiRelayout', gd, aobj);
}
@@ -27504,22 +27410,32 @@ function handleCamera3d(gd, ev) {
var button = ev.currentTarget;
var attr = button.getAttribute('data-attr');
var fullLayout = gd._fullLayout;
- var sceneIds = fullLayout._subplots.gl3d;
+ var sceneIds = fullLayout._subplots.gl3d || [];
var aobj = {};
for(var i = 0; i < sceneIds.length; i++) {
var sceneId = sceneIds[i];
- var key = sceneId + '.camera';
+ var camera = sceneId + '.camera';
+ var aspectratio = sceneId + '.aspectratio';
var scene = fullLayout[sceneId]._scene;
+ var didUpdate;
if(attr === 'resetLastSave') {
- aobj[key + '.up'] = scene.viewInitial.up;
- aobj[key + '.eye'] = scene.viewInitial.eye;
- aobj[key + '.center'] = scene.viewInitial.center;
+ aobj[camera + '.up'] = scene.viewInitial.up;
+ aobj[camera + '.eye'] = scene.viewInitial.eye;
+ aobj[camera + '.center'] = scene.viewInitial.center;
+ didUpdate = true;
} else if(attr === 'resetDefault') {
- aobj[key + '.up'] = null;
- aobj[key + '.eye'] = null;
- aobj[key + '.center'] = null;
+ aobj[camera + '.up'] = null;
+ aobj[camera + '.eye'] = null;
+ aobj[camera + '.center'] = null;
+ didUpdate = true;
+ }
+
+ if(didUpdate) {
+ aobj[aspectratio + '.x'] = scene.viewInitial.aspectratio.x;
+ aobj[aspectratio + '.y'] = scene.viewInitial.aspectratio.y;
+ aobj[aspectratio + '.z'] = scene.viewInitial.aspectratio.z;
}
}
@@ -27541,7 +27457,7 @@ function getNextHover3d(gd, ev) {
var button = ev.currentTarget;
var val = button._previousVal;
var fullLayout = gd._fullLayout;
- var sceneIds = fullLayout._subplots.gl3d;
+ var sceneIds = fullLayout._subplots.gl3d || [];
var axes = ['xaxis', 'yaxis', 'zaxis'];
@@ -27742,26 +27658,22 @@ modeBarButtons.toggleSpikelines = {
val: 'on',
click: function(gd) {
var fullLayout = gd._fullLayout;
+ var allSpikesEnabled = fullLayout._cartesianSpikesEnabled;
- fullLayout._cartesianSpikesEnabled = fullLayout._cartesianSpikesEnabled === 'on' ? 'off' : 'on';
-
- var aobj = setSpikelineVisibility(gd);
-
- Registry.call('_guiRelayout', gd, aobj);
+ fullLayout._cartesianSpikesEnabled = allSpikesEnabled === 'on' ? 'off' : 'on';
+ Registry.call('_guiRelayout', gd, setSpikelineVisibility(gd));
}
};
function setSpikelineVisibility(gd) {
var fullLayout = gd._fullLayout;
+ var areSpikesOn = fullLayout._cartesianSpikesEnabled === 'on';
var axList = axisIds.list(gd, null, true);
var aobj = {};
- var ax, axName;
-
for(var i = 0; i < axList.length; i++) {
- ax = axList[i];
- axName = ax._name;
- aobj[axName + '.showspikes'] = fullLayout._cartesianSpikesEnabled === 'on' ? true : ax._showSpikeInitial;
+ var ax = axList[i];
+ aobj[ax._name + '.showspikes'] = areSpikesOn ? true : ax._showSpikeInitial;
}
return aobj;
@@ -27779,7 +27691,7 @@ modeBarButtons.resetViewMapbox = {
function resetView(gd, subplotType) {
var fullLayout = gd._fullLayout;
- var subplotIds = fullLayout._subplots[subplotType];
+ var subplotIds = fullLayout._subplots[subplotType] || [];
var aObj = {};
for(var i = 0; i < subplotIds.length; i++) {
@@ -27797,7 +27709,7 @@ function resetView(gd, subplotType) {
Registry.call('_guiRelayout', gd, aObj);
}
-},{"../../../build/ploticon":2,"../../lib":168,"../../plots/cartesian/axis_ids":215,"../../plots/plots":244,"../../registry":256}],110:[function(_dereq_,module,exports){
+},{"../../fonts/ploticon":153,"../../lib":169,"../../plots/cartesian/axis_ids":216,"../../plots/plots":245,"../../registry":258}],109:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -27811,7 +27723,7 @@ function resetView(gd, subplotType) {
exports.manage = _dereq_('./manage');
-},{"./manage":111}],111:[function(_dereq_,module,exports){
+},{"./manage":110}],110:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -27873,12 +27785,7 @@ module.exports = function manageModeBar(gd) {
} else if(!context.displayModeBar && context.watermark) {
buttonGroups = [];
} else {
- buttonGroups = getButtonGroups(
- gd,
- context.modeBarButtonsToRemove,
- context.modeBarButtonsToAdd,
- context.showSendToCloud
- );
+ buttonGroups = getButtonGroups(gd);
}
if(modeBar) modeBar.update(gd, buttonGroups);
@@ -27886,9 +27793,12 @@ module.exports = function manageModeBar(gd) {
};
// logic behind which buttons are displayed by default
-function getButtonGroups(gd, buttonsToRemove, buttonsToAdd, showSendToCloud) {
+function getButtonGroups(gd) {
var fullLayout = gd._fullLayout;
var fullData = gd._fullData;
+ var context = gd._context;
+ var buttonsToRemove = context.modeBarButtonsToRemove;
+ var buttonsToAdd = context.modeBarButtonsToAdd;
var hasCartesian = fullLayout._has('cartesian');
var hasGL3D = fullLayout._has('gl3d');
@@ -27920,7 +27830,8 @@ function getButtonGroups(gd, buttonsToRemove, buttonsToAdd, showSendToCloud) {
// buttons common to all plot types
var commonGroup = ['toImage'];
- if(showSendToCloud) commonGroup.push('sendDataToCloud');
+ if(context.showEditInChartStudio) commonGroup.push('editInChartStudio');
+ else if(context.showSendToCloud) commonGroup.push('sendDataToCloud');
addGroup(commonGroup);
var zoomGroup = [];
@@ -27960,6 +27871,9 @@ function getButtonGroups(gd, buttonsToRemove, buttonsToAdd, showSendToCloud) {
if(hasCartesian) {
hoverGroup = ['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian'];
}
+ if(hasNoHover(fullData)) {
+ hoverGroup = [];
+ }
if((hasCartesian || hasGL2D) && !allAxesFixed) {
zoomGroup = ['zoomIn2d', 'zoomOut2d', 'autoScale2d'];
@@ -28030,6 +27944,14 @@ function isSelectable(fullData) {
return selectable;
}
+// check whether all trace are 'noHover'
+function hasNoHover(fullData) {
+ for(var i = 0; i < fullData.length; i++) {
+ if(!Registry.traceIs(fullData[i], 'noHover')) return false;
+ }
+ return true;
+}
+
function appendButtonsToGroups(groups, buttons) {
if(buttons.length) {
if(Array.isArray(buttons[0])) {
@@ -28066,7 +27988,7 @@ function fillCustomButton(customButtons) {
return customButtons;
}
-},{"../../plots/cartesian/axis_ids":215,"../../registry":256,"../../traces/scatter/subtypes":388,"./buttons":109,"./modebar":112}],112:[function(_dereq_,module,exports){
+},{"../../plots/cartesian/axis_ids":216,"../../registry":258,"../../traces/scatter/subtypes":401,"./buttons":108,"./modebar":111}],111:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -28082,7 +28004,7 @@ var d3 = _dereq_('d3');
var isNumeric = _dereq_('fast-isnumeric');
var Lib = _dereq_('../../lib');
-var Icons = _dereq_('../../../build/ploticon');
+var Icons = _dereq_('../../fonts/ploticon');
var Parser = new DOMParser();
/**
@@ -28412,7 +28334,7 @@ function createModeBar(gd, buttons) {
module.exports = createModeBar;
-},{"../../../build/ploticon":2,"../../lib":168,"d3":16,"fast-isnumeric":18}],113:[function(_dereq_,module,exports){
+},{"../../fonts/ploticon":153,"../../lib":169,"d3":16,"fast-isnumeric":18}],112:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -28548,7 +28470,7 @@ module.exports = {
editType: 'plot'
};
-},{"../../plot_api/plot_template":202,"../../plots/font_attributes":238,"../color/attributes":50}],114:[function(_dereq_,module,exports){
+},{"../../plot_api/plot_template":203,"../../plots/font_attributes":239,"../color/attributes":50}],113:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -28577,7 +28499,7 @@ module.exports = {
darkAmount: 10
};
-},{}],115:[function(_dereq_,module,exports){
+},{}],114:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -28669,7 +28591,7 @@ function getPosDflt(containerOut, layout, counterAxes) {
return [containerOut.domain[0], posY + constants.yPad];
}
-},{"../../lib":168,"../../plot_api/plot_template":202,"../../plots/array_container_defaults":208,"../color":51,"./attributes":113,"./constants":114}],116:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plot_api/plot_template":203,"../../plots/array_container_defaults":209,"../color":51,"./attributes":112,"./constants":113}],115:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -28926,7 +28848,7 @@ function reposition(gd, buttons, opts, axName, selector) {
selector.attr('transform', 'translate(' + lx + ',' + ly + ')');
}
-},{"../../constants/alignment":146,"../../lib":168,"../../lib/svg_text_utils":189,"../../plots/cartesian/axis_ids":215,"../../plots/plots":244,"../../registry":256,"../color":51,"../drawing":72,"./constants":114,"./get_update_object":117,"d3":16}],117:[function(_dereq_,module,exports){
+},{"../../constants/alignment":145,"../../lib":169,"../../lib/svg_text_utils":190,"../../plots/cartesian/axis_ids":216,"../../plots/plots":245,"../../registry":258,"../color":51,"../drawing":72,"./constants":113,"./get_update_object":116,"d3":16}],116:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -28980,7 +28902,7 @@ function getXRange(axisLayout, buttonLayout) {
return [range0, range1];
}
-},{"d3":16}],118:[function(_dereq_,module,exports){
+},{"d3":16}],117:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -29007,7 +28929,7 @@ module.exports = {
draw: _dereq_('./draw')
};
-},{"./attributes":113,"./defaults":115,"./draw":116}],119:[function(_dereq_,module,exports){
+},{"./attributes":112,"./defaults":114,"./draw":115}],118:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -29081,7 +29003,7 @@ module.exports = {
editType: 'calc'
};
-},{"../color/attributes":50}],120:[function(_dereq_,module,exports){
+},{"../color/attributes":50}],119:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -29115,7 +29037,7 @@ module.exports = function calcAutorange(gd) {
}
};
-},{"../../plots/cartesian/autorange":211,"../../plots/cartesian/axis_ids":215,"./constants":121}],121:[function(_dereq_,module,exports){
+},{"../../plots/cartesian/autorange":212,"../../plots/cartesian/axis_ids":216,"./constants":120}],120:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -29171,7 +29093,7 @@ module.exports = {
extraPad: 15
};
-},{}],122:[function(_dereq_,module,exports){
+},{}],121:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -29257,7 +29179,7 @@ module.exports = function handleDefaults(layoutIn, layoutOut, axName) {
containerOut._input = containerIn;
};
-},{"../../lib":168,"../../plot_api/plot_template":202,"../../plots/cartesian/axis_ids":215,"./attributes":119,"./oppaxis_attributes":126}],123:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plot_api/plot_template":203,"../../plots/cartesian/axis_ids":216,"./attributes":118,"./oppaxis_attributes":125}],122:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -29366,20 +29288,16 @@ module.exports = function(gd) {
// update range slider dimensions
- var margin = fullLayout.margin;
- var graphSize = fullLayout._size;
+ var gs = fullLayout._size;
var domain = axisOpts.domain;
- var tickHeight = opts._tickHeight;
- var oppBottom = opts._oppBottom;
+ opts._width = gs.w * (domain[1] - domain[0]);
- opts._width = graphSize.w * (domain[1] - domain[0]);
-
- var x = Math.round(margin.l + (graphSize.w * domain[0]));
+ var x = Math.round(gs.l + (gs.w * domain[0]));
var y = Math.round(
- graphSize.t + graphSize.h * (1 - oppBottom) +
- tickHeight +
+ gs.t + gs.h * (1 - axisOpts._counterDomainMin) +
+ (axisOpts.side === 'bottom' ? axisOpts._depth : 0) +
opts._offsetShift + constants.extraPad
);
@@ -29837,7 +29755,7 @@ function drawGrabbers(rangeSlider, gd, axisOpts, opts) {
grabAreaMax.attr('height', opts._height);
}
-},{"../../lib":168,"../../lib/setcursor":187,"../../plots/cartesian":223,"../../plots/cartesian/axis_ids":215,"../../plots/plots":244,"../../registry":256,"../color":51,"../dragelement":69,"../drawing":72,"../titles":139,"./constants":121,"d3":16}],124:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../lib/setcursor":188,"../../plots/cartesian":224,"../../plots/cartesian/axis_ids":216,"../../plots/plots":245,"../../registry":258,"../color":51,"../dragelement":69,"../drawing":72,"../titles":138,"./constants":120,"d3":16}],123:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -29849,7 +29767,9 @@ function drawGrabbers(rangeSlider, gd, axisOpts, opts) {
'use strict';
var axisIDs = _dereq_('../../plots/cartesian/axis_ids');
+var svgTextUtils = _dereq_('../../lib/svg_text_utils');
var constants = _dereq_('./constants');
+var LINE_SPACING = _dereq_('../../constants/alignment').LINE_SPACING;
var name = constants.name;
function isVisible(ax) {
@@ -29882,32 +29802,35 @@ exports.makeData = function(fullLayout) {
};
exports.autoMarginOpts = function(gd, ax) {
+ var fullLayout = gd._fullLayout;
var opts = ax[name];
+ var axLetter = ax._id.charAt(0);
- var oppBottom = Infinity;
- var counterAxes = ax._counterAxes;
- for(var j = 0; j < counterAxes.length; j++) {
- var counterId = counterAxes[j];
- var oppAxis = axisIDs.getFromId(gd, counterId);
- oppBottom = Math.min(oppBottom, oppAxis.domain[0]);
+ var bottomDepth = 0;
+ var titleHeight = 0;
+ if(ax.side === 'bottom') {
+ bottomDepth = ax._depth;
+ if(ax.title.text !== fullLayout._dfltTitle[axLetter]) {
+ // as in rangeslider/draw.js
+ titleHeight = 1.5 * ax.title.font.size + 10 + opts._offsetShift;
+ // multi-line extra bump
+ var extraLines = (ax.title.text.match(svgTextUtils.BR_TAG_ALL) || []).length;
+ titleHeight += extraLines * ax.title.font.size * LINE_SPACING;
+ }
}
- opts._oppBottom = oppBottom;
-
- var tickHeight = (ax.side === 'bottom' && ax._boundingBox.height) || 0;
- opts._tickHeight = tickHeight;
return {
x: 0,
- y: oppBottom,
+ y: ax._counterDomainMin,
l: 0,
r: 0,
t: 0,
- b: opts._height + gd._fullLayout.margin.b + tickHeight,
+ b: opts._height + bottomDepth + Math.max(fullLayout.margin.b, titleHeight),
pad: constants.extraPad + opts._offsetShift * 2
};
};
-},{"../../plots/cartesian/axis_ids":215,"./constants":121}],125:[function(_dereq_,module,exports){
+},{"../../constants/alignment":145,"../../lib/svg_text_utils":190,"../../plots/cartesian/axis_ids":216,"./constants":120}],124:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -29946,7 +29869,7 @@ module.exports = {
autoMarginOpts: helpers.autoMarginOpts
};
-},{"../../lib":168,"./attributes":119,"./calc_autorange":120,"./defaults":122,"./draw":123,"./helpers":124,"./oppaxis_attributes":126}],126:[function(_dereq_,module,exports){
+},{"../../lib":169,"./attributes":118,"./calc_autorange":119,"./defaults":121,"./draw":122,"./helpers":123,"./oppaxis_attributes":125}],125:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -29984,7 +29907,7 @@ module.exports = {
editType: 'calc'
};
-},{}],127:[function(_dereq_,module,exports){
+},{}],126:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -30120,7 +30043,7 @@ module.exports = templatedArray('shape', {
editType: 'arraydraw'
});
-},{"../../lib/extend":162,"../../plot_api/plot_template":202,"../../traces/scatter/attributes":365,"../annotations/attributes":36,"../drawing/attributes":71}],128:[function(_dereq_,module,exports){
+},{"../../lib/extend":164,"../../plot_api/plot_template":203,"../../traces/scatter/attributes":377,"../annotations/attributes":36,"../drawing/attributes":71}],127:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -30237,7 +30160,7 @@ function shapeBounds(ax, v0, v1, path, paramsToUse) {
if(max >= min) return [min, max];
}
-},{"../../lib":168,"../../plots/cartesian/axes":212,"./constants":129,"./helpers":132}],129:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/cartesian/axes":213,"./constants":128,"./helpers":131}],128:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -30301,7 +30224,7 @@ module.exports = {
}
};
-},{}],130:[function(_dereq_,module,exports){
+},{}],129:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -30424,7 +30347,7 @@ function handleShapeDefaults(shapeIn, shapeOut, fullLayout) {
}
}
-},{"../../lib":168,"../../plots/array_container_defaults":208,"../../plots/cartesian/axes":212,"./attributes":127,"./helpers":132}],131:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/array_container_defaults":209,"../../plots/cartesian/axes":213,"./attributes":126,"./helpers":131}],130:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -31041,7 +30964,7 @@ function movePath(pathIn, moveX, moveY) {
});
}
-},{"../../lib":168,"../../lib/setcursor":187,"../../plot_api/plot_template":202,"../../plots/cartesian/axes":212,"../../registry":256,"../color":51,"../dragelement":69,"../drawing":72,"./constants":129,"./helpers":132}],132:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../lib/setcursor":188,"../../plot_api/plot_template":203,"../../plots/cartesian/axes":213,"../../registry":258,"../color":51,"../dragelement":69,"../drawing":72,"./constants":128,"./helpers":131}],131:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -31162,7 +31085,7 @@ exports.roundPositionForSharpStrokeRendering = function(pos, strokeWidth) {
return strokeWidthIsOdd ? posValAsInt + 0.5 : posValAsInt;
};
-},{"../../lib":168,"./constants":129}],133:[function(_dereq_,module,exports){
+},{"../../lib":169,"./constants":128}],132:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -31189,7 +31112,7 @@ module.exports = {
drawOne: drawModule.drawOne
};
-},{"../../plots/cartesian/include_components":222,"./attributes":127,"./calc_autorange":128,"./defaults":130,"./draw":131}],134:[function(_dereq_,module,exports){
+},{"../../plots/cartesian/include_components":223,"./attributes":126,"./calc_autorange":127,"./defaults":129,"./draw":130}],133:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -31432,7 +31355,7 @@ module.exports = overrideAll(templatedArray('slider', {
}
}), 'arraydraw', 'from-root');
-},{"../../lib/extend":162,"../../plot_api/edit_types":195,"../../plot_api/plot_template":202,"../../plots/animation_attributes":207,"../../plots/font_attributes":238,"../../plots/pad_attributes":243,"./constants":135}],135:[function(_dereq_,module,exports){
+},{"../../lib/extend":164,"../../plot_api/edit_types":196,"../../plot_api/plot_template":203,"../../plots/animation_attributes":208,"../../plots/font_attributes":239,"../../plots/pad_attributes":244,"./constants":134}],134:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -31526,7 +31449,7 @@ module.exports = {
currentValueInset: 0,
};
-},{}],136:[function(_dereq_,module,exports){
+},{}],135:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -31641,7 +31564,7 @@ function stepDefaults(valueIn, valueOut) {
}
}
-},{"../../lib":168,"../../plots/array_container_defaults":208,"./attributes":134,"./constants":135}],137:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/array_container_defaults":209,"./attributes":133,"./constants":134}],136:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -32273,7 +32196,7 @@ function drawRail(sliderGroup, sliderOpts) {
);
}
-},{"../../constants/alignment":146,"../../lib":168,"../../lib/svg_text_utils":189,"../../plot_api/plot_template":202,"../../plots/plots":244,"../color":51,"../drawing":72,"./constants":135,"d3":16}],138:[function(_dereq_,module,exports){
+},{"../../constants/alignment":145,"../../lib":169,"../../lib/svg_text_utils":190,"../../plot_api/plot_template":203,"../../plots/plots":245,"../color":51,"../drawing":72,"./constants":134,"d3":16}],137:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -32296,7 +32219,7 @@ module.exports = {
draw: _dereq_('./draw')
};
-},{"./attributes":134,"./constants":135,"./defaults":136,"./draw":137}],139:[function(_dereq_,module,exports){
+},{"./attributes":133,"./constants":134,"./defaults":135,"./draw":136}],138:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -32319,10 +32242,7 @@ var Color = _dereq_('../color');
var svgTextUtils = _dereq_('../../lib/svg_text_utils');
var interactConstants = _dereq_('../../constants/interactions');
-module.exports = {
- draw: draw
-};
-
+var OPPOSITE_SIDE = _dereq_('../../constants/alignment').OPPOSITE_SIDE;
var numStripRE = / [XY][0-9]* /;
/**
@@ -32466,16 +32386,10 @@ function draw(gd, titleClass, options) {
// move toward avoid.side (= left, right, top, bottom) if needed
// can include pad (pixels, default 2)
- var shift = 0;
- var backside = {
- left: 'right',
- right: 'left',
- top: 'bottom',
- bottom: 'top'
- }[avoid.side];
- var shiftSign = (['left', 'top'].indexOf(avoid.side) !== -1) ?
- -1 : 1;
+ var backside = OPPOSITE_SIDE[avoid.side];
+ var shiftSign = (avoid.side === 'left' || avoid.side === 'top') ? -1 : 1;
var pad = isNumeric(avoid.pad) ? avoid.pad : 2;
+
var titlebb = Drawing.bBox(titleGroup.node());
var paperbb = {
left: 0,
@@ -32483,12 +32397,15 @@ function draw(gd, titleClass, options) {
right: fullLayout.width,
bottom: fullLayout.height
};
- var maxshift = avoid.maxShift || (
- (paperbb[avoid.side] - titlebb[avoid.side]) *
- ((avoid.side === 'left' || avoid.side === 'top') ? -1 : 1));
+
+ var maxshift = avoid.maxShift ||
+ shiftSign * (paperbb[avoid.side] - titlebb[avoid.side]);
+ var shift = 0;
+
// Prevent the title going off the paper
- if(maxshift < 0) shift = maxshift;
- else {
+ if(maxshift < 0) {
+ shift = maxshift;
+ } else {
// so we don't have to offset each avoided element,
// give the title the opposite offset
var offsetLeft = avoid.offsetLeft || 0;
@@ -32510,6 +32427,7 @@ function draw(gd, titleClass, options) {
});
shift = Math.min(maxshift, shift);
}
+
if(shift > 0 || maxshift < 0) {
var shiftTemplate = {
left: [-shift, 0],
@@ -32517,8 +32435,7 @@ function draw(gd, titleClass, options) {
top: [0, -shift],
bottom: [0, shift]
}[avoid.side];
- titleGroup.attr('transform',
- 'translate(' + shiftTemplate + ')');
+ titleGroup.attr('transform', 'translate(' + shiftTemplate + ')');
}
}
}
@@ -32565,7 +32482,11 @@ function draw(gd, titleClass, options) {
return group;
}
-},{"../../constants/interactions":148,"../../lib":168,"../../lib/svg_text_utils":189,"../../plots/plots":244,"../../registry":256,"../color":51,"../drawing":72,"d3":16,"fast-isnumeric":18}],140:[function(_dereq_,module,exports){
+module.exports = {
+ draw: draw
+};
+
+},{"../../constants/alignment":145,"../../constants/interactions":148,"../../lib":169,"../../lib/svg_text_utils":190,"../../plots/plots":245,"../../registry":258,"../color":51,"../drawing":72,"d3":16,"fast-isnumeric":18}],139:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -32606,6 +32527,17 @@ var buttonsAttrs = templatedArray('button', {
{valType: 'any'}
],
+ },
+ args2: {
+ valType: 'info_array',
+
+ freeLength: true,
+ items: [
+ {valType: 'any'},
+ {valType: 'any'},
+ {valType: 'any'}
+ ],
+
},
label: {
valType: 'string',
@@ -32723,7 +32655,7 @@ module.exports = overrideAll(templatedArray('updatemenu', {
}
}), 'arraydraw', 'from-root');
-},{"../../lib/extend":162,"../../plot_api/edit_types":195,"../../plot_api/plot_template":202,"../../plots/font_attributes":238,"../../plots/pad_attributes":243,"../color/attributes":50}],141:[function(_dereq_,module,exports){
+},{"../../lib/extend":164,"../../plot_api/edit_types":196,"../../plot_api/plot_template":203,"../../plots/font_attributes":239,"../../plots/pad_attributes":244,"../color/attributes":50}],140:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -32804,7 +32736,7 @@ module.exports = {
}
};
-},{}],142:[function(_dereq_,module,exports){
+},{}],141:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -32881,12 +32813,13 @@ function buttonDefaults(buttonIn, buttonOut) {
if(visible) {
coerce('method');
coerce('args');
+ coerce('args2');
coerce('label');
coerce('execute');
}
}
-},{"../../lib":168,"../../plots/array_container_defaults":208,"./attributes":140,"./constants":141}],143:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/array_container_defaults":209,"./attributes":139,"./constants":140}],142:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -33008,6 +32941,7 @@ module.exports = function draw(gd) {
var gHeader = d3.select(this);
var _gButton = menuOpts.type === 'dropdown' ? gButton : null;
+
Plots.manageCommandObserver(gd, menuOpts, menuOpts.buttons, function(data) {
setActive(gd, menuOpts, menuOpts.buttons[data.index], gHeader, _gButton, scrollBox, data.index, true);
});
@@ -33195,10 +33129,14 @@ function drawButtons(gd, gHeader, gButton, scrollBox, menuOpts) {
// skip `dragend` events
if(d3.event.defaultPrevented) return;
- setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, buttonIndex);
-
if(buttonOpts.execute) {
- Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args);
+ if(buttonOpts.args2 && menuOpts.active === buttonIndex) {
+ setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, -1);
+ Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args2);
+ } else {
+ setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, buttonIndex);
+ Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args);
+ }
}
gd.emit('plotly_buttonclicked', {menu: menuOpts, button: buttonOpts, active: menuOpts.active});
@@ -33534,9 +33472,9 @@ function removeAllButtons(gButton, newMenuIndexAttr) {
.selectAll('g.' + constants.dropdownButtonClassName).remove();
}
-},{"../../constants/alignment":146,"../../lib":168,"../../lib/svg_text_utils":189,"../../plot_api/plot_template":202,"../../plots/plots":244,"../color":51,"../drawing":72,"./constants":141,"./scrollbox":145,"d3":16}],144:[function(_dereq_,module,exports){
-arguments[4][138][0].apply(exports,arguments)
-},{"./attributes":140,"./constants":141,"./defaults":142,"./draw":143,"dup":138}],145:[function(_dereq_,module,exports){
+},{"../../constants/alignment":145,"../../lib":169,"../../lib/svg_text_utils":190,"../../plot_api/plot_template":203,"../../plots/plots":245,"../color":51,"../drawing":72,"./constants":140,"./scrollbox":144,"d3":16}],143:[function(_dereq_,module,exports){
+arguments[4][137][0].apply(exports,arguments)
+},{"./attributes":139,"./constants":140,"./defaults":141,"./draw":142,"dup":137}],144:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -34001,7 +33939,7 @@ ScrollBox.prototype.setTranslate = function setTranslate(translateX, translateY)
}
};
-},{"../../lib":168,"../color":51,"../drawing":72,"d3":16}],146:[function(_dereq_,module,exports){
+},{"../../lib":169,"../color":51,"../drawing":72,"d3":16}],145:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -34066,6 +34004,22 @@ module.exports = {
}
};
+},{}],146:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+module.exports = {
+ FORMAT_LINK: 'https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md#d3_format',
+ DATE_FORMAT_LINK: 'https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Formatting.md#format'
+};
+
},{}],147:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
@@ -34123,10 +34077,6 @@ module.exports = {
SHOW_PLACEHOLDER: 100,
HIDE_PLACEHOLDER: 1000,
- // ms between first mousedown and 2nd mouseup to constitute dblclick...
- // we don't seem to have access to the system setting
- DBLCLICKDELAY: 300,
-
// opacity dimming fraction for points that are not in selection
DESELECTDIM: 0.2
};
@@ -34232,7 +34182,7 @@ exports.svgAttrs = {
'use strict';
// package version injected by `npm run preprocess`
-exports.version = '1.48.2';
+exports.version = '1.51.3';
// inject promise polyfill
_dereq_('es6-promise').polyfill();
@@ -34289,7 +34239,7 @@ register([
]);
// plot icons
-exports.Icons = _dereq_('../build/ploticon');
+exports.Icons = _dereq_('./fonts/ploticon');
// unofficial 'beta' plot methods, use at your own risk
exports.Plots = _dereq_('./plots/plots');
@@ -34301,7 +34251,7 @@ exports.Queue = _dereq_('./lib/queue');
// export d3 used in the bundle
exports.d3 = _dereq_('d3');
-},{"../build/plotcss":1,"../build/ploticon":2,"./components/annotations":44,"./components/annotations3d":49,"./components/colorbar":57,"./components/colorscale":63,"./components/errorbars":78,"./components/fx":90,"./components/grid":94,"./components/images":99,"./components/legend":107,"./components/rangeselector":118,"./components/rangeslider":125,"./components/shapes":133,"./components/sliders":138,"./components/updatemenus":144,"./fonts/mathjax_config":152,"./lib/queue":182,"./locale-en":193,"./locale-en-us":192,"./plot_api":197,"./plot_api/plot_schema":201,"./plots/plots":244,"./registry":256,"./snapshot":261,"./traces/scatter":376,"d3":16,"es6-promise":17}],152:[function(_dereq_,module,exports){
+},{"../build/plotcss":1,"./components/annotations":44,"./components/annotations3d":49,"./components/colorbar":57,"./components/colorscale":63,"./components/errorbars":78,"./components/fx":89,"./components/grid":93,"./components/images":98,"./components/legend":106,"./components/rangeselector":117,"./components/rangeslider":124,"./components/shapes":132,"./components/sliders":137,"./components/updatemenus":143,"./fonts/mathjax_config":152,"./fonts/ploticon":153,"./lib/queue":183,"./locale-en":194,"./locale-en-us":193,"./plot_api":198,"./plot_api/plot_schema":202,"./plots/plots":245,"./registry":258,"./snapshot":263,"./traces/scatter":389,"d3":16,"es6-promise":17}],152:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -34341,6 +34291,150 @@ module.exports = function() {
* LICENSE file in the root directory of this source tree.
*/
+'use strict';
+
+module.exports = {
+ 'undo': {
+ 'width': 857.1,
+ 'height': 1000,
+ 'path': 'm857 350q0-87-34-166t-91-137-137-92-166-34q-96 0-183 41t-147 114q-4 6-4 13t5 11l76 77q6 5 14 5 9-1 13-7 41-53 100-82t126-29q58 0 110 23t92 61 61 91 22 111-22 111-61 91-92 61-110 23q-55 0-105-20t-90-57l77-77q17-16 8-38-10-23-33-23h-250q-15 0-25 11t-11 25v250q0 24 22 33 22 10 39-8l72-72q60 57 137 88t159 31q87 0 166-34t137-92 91-137 34-166z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'home': {
+ 'width': 928.6,
+ 'height': 1000,
+ 'path': 'm786 296v-267q0-15-11-26t-25-10h-214v214h-143v-214h-214q-15 0-25 10t-11 26v267q0 1 0 2t0 2l321 264 321-264q1-1 1-4z m124 39l-34-41q-5-5-12-6h-2q-7 0-12 3l-386 322-386-322q-7-4-13-4-7 2-12 7l-35 41q-4 5-3 13t6 12l401 334q18 15 42 15t43-15l136-114v109q0 8 5 13t13 5h107q8 0 13-5t5-13v-227l122-102q5-5 6-12t-4-13z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'camera-retro': {
+ 'width': 1000,
+ 'height': 1000,
+ 'path': 'm518 386q0 8-5 13t-13 5q-37 0-63-27t-26-63q0-8 5-13t13-5 12 5 5 13q0 23 16 38t38 16q8 0 13 5t5 13z m125-73q0-59-42-101t-101-42-101 42-42 101 42 101 101 42 101-42 42-101z m-572-320h858v71h-858v-71z m643 320q0 89-62 152t-152 62-151-62-63-152 63-151 151-63 152 63 62 151z m-571 358h214v72h-214v-72z m-72-107h858v143h-462l-36-71h-360v-72z m929 143v-714q0-30-21-51t-50-21h-858q-29 0-50 21t-21 51v714q0 30 21 51t50 21h858q29 0 50-21t21-51z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'zoombox': {
+ 'width': 1000,
+ 'height': 1000,
+ 'path': 'm1000-25l-250 251c40 63 63 138 63 218 0 224-182 406-407 406-224 0-406-182-406-406s183-406 407-406c80 0 155 22 218 62l250-250 125 125z m-812 250l0 438 437 0 0-438-437 0z m62 375l313 0 0-312-313 0 0 312z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'pan': {
+ 'width': 1000,
+ 'height': 1000,
+ 'path': 'm1000 350l-187 188 0-125-250 0 0 250 125 0-188 187-187-187 125 0 0-250-250 0 0 125-188-188 186-187 0 125 252 0 0-250-125 0 187-188 188 188-125 0 0 250 250 0 0-126 187 188z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'zoom_plus': {
+ 'width': 875,
+ 'height': 1000,
+ 'path': 'm1 787l0-875 875 0 0 875-875 0z m687-500l-187 0 0-187-125 0 0 187-188 0 0 125 188 0 0 187 125 0 0-187 187 0 0-125z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'zoom_minus': {
+ 'width': 875,
+ 'height': 1000,
+ 'path': 'm0 788l0-876 875 0 0 876-875 0z m688-500l-500 0 0 125 500 0 0-125z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'autoscale': {
+ 'width': 1000,
+ 'height': 1000,
+ 'path': 'm250 850l-187 0-63 0 0-62 0-188 63 0 0 188 187 0 0 62z m688 0l-188 0 0-62 188 0 0-188 62 0 0 188 0 62-62 0z m-875-938l0 188-63 0 0-188 0-62 63 0 187 0 0 62-187 0z m875 188l0-188-188 0 0-62 188 0 62 0 0 62 0 188-62 0z m-125 188l-1 0-93-94-156 156 156 156 92-93 2 0 0 250-250 0 0-2 93-92-156-156-156 156 94 92 0 2-250 0 0-250 0 0 93 93 157-156-157-156-93 94 0 0 0-250 250 0 0 0-94 93 156 157 156-157-93-93 0 0 250 0 0 250z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'tooltip_basic': {
+ 'width': 1500,
+ 'height': 1000,
+ 'path': 'm375 725l0 0-375-375 375-374 0-1 1125 0 0 750-1125 0z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'tooltip_compare': {
+ 'width': 1125,
+ 'height': 1000,
+ 'path': 'm187 786l0 2-187-188 188-187 0 0 937 0 0 373-938 0z m0-499l0 1-187-188 188-188 0 0 937 0 0 376-938-1z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'plotlylogo': {
+ 'width': 1542,
+ 'height': 1000,
+ 'path': 'm0-10h182v-140h-182v140z m228 146h183v-286h-183v286z m225 714h182v-1000h-182v1000z m225-285h182v-715h-182v715z m225 142h183v-857h-183v857z m231-428h182v-429h-182v429z m225-291h183v-138h-183v138z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'z-axis': {
+ 'width': 1000,
+ 'height': 1000,
+ 'path': 'm833 5l-17 108v41l-130-65 130-66c0 0 0 38 0 39 0-1 36-14 39-25 4-15-6-22-16-30-15-12-39-16-56-20-90-22-187-23-279-23-261 0-341 34-353 59 3 60 228 110 228 110-140-8-351-35-351-116 0-120 293-142 474-142 155 0 477 22 477 142 0 50-74 79-163 96z m-374 94c-58-5-99-21-99-40 0-24 65-43 144-43 79 0 143 19 143 43 0 19-42 34-98 40v216h87l-132 135-133-135h88v-216z m167 515h-136v1c16 16 31 34 46 52l84 109v54h-230v-71h124v-1c-16-17-28-32-44-51l-89-114v-51h245v72z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ '3d_rotate': {
+ 'width': 1000,
+ 'height': 1000,
+ 'path': 'm922 660c-5 4-9 7-14 11-359 263-580-31-580-31l-102 28 58-400c0 1 1 1 2 2 118 108 351 249 351 249s-62 27-100 42c88 83 222 183 347 122 16-8 30-17 44-27-2 1-4 2-6 4z m36-329c0 0 64 229-88 296-62 27-124 14-175-11 157-78 225-208 249-266 8-19 11-31 11-31 2 5 6 15 11 32-5-13-8-20-8-20z m-775-239c70-31 117-50 198-32-121 80-199 346-199 346l-96-15-58-12c0 0 55-226 155-287z m603 133l-317-139c0 0 4-4 19-14 7-5 24-15 24-15s-177-147-389 4c235-287 536-112 536-112l31-22 100 299-4-1z m-298-153c6-4 14-9 24-15 0 0-17 10-24 15z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'camera': {
+ 'width': 1000,
+ 'height': 1000,
+ 'path': 'm500 450c-83 0-150-67-150-150 0-83 67-150 150-150 83 0 150 67 150 150 0 83-67 150-150 150z m400 150h-120c-16 0-34 13-39 29l-31 93c-6 15-23 28-40 28h-340c-16 0-34-13-39-28l-31-94c-6-15-23-28-40-28h-120c-55 0-100-45-100-100v-450c0-55 45-100 100-100h800c55 0 100 45 100 100v450c0 55-45 100-100 100z m-400-550c-138 0-250 112-250 250 0 138 112 250 250 250 138 0 250-112 250-250 0-138-112-250-250-250z m365 380c-19 0-35 16-35 35 0 19 16 35 35 35 19 0 35-16 35-35 0-19-16-35-35-35z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'movie': {
+ 'width': 1000,
+ 'height': 1000,
+ 'path': 'm938 413l-188-125c0 37-17 71-44 94 64 38 107 107 107 187 0 121-98 219-219 219-121 0-219-98-219-219 0-61 25-117 66-156h-115c30 33 49 76 49 125 0 103-84 187-187 187s-188-84-188-187c0-57 26-107 65-141-38-22-65-62-65-109v-250c0-70 56-126 125-126h500c69 0 125 56 125 126l188-126c34 0 62 28 62 63v375c0 35-28 63-62 63z m-750 0c-69 0-125 56-125 125s56 125 125 125 125-56 125-125-56-125-125-125z m406-1c-87 0-157 70-157 157 0 86 70 156 157 156s156-70 156-156-70-157-156-157z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'question': {
+ 'width': 857.1,
+ 'height': 1000,
+ 'path': 'm500 82v107q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h107q8 0 13 5t5 13z m143 375q0 49-31 91t-77 65-95 23q-136 0-207-119-9-14 4-24l74-55q4-4 10-4 9 0 14 7 30 38 48 51 19 14 48 14 27 0 48-15t21-33q0-21-11-34t-38-25q-35-16-65-48t-29-70v-20q0-8 5-13t13-5h107q8 0 13 5t5 13q0 10 12 27t30 28q18 10 28 16t25 19 25 27 16 34 7 45z m214-107q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'disk': {
+ 'width': 857.1,
+ 'height': 1000,
+ 'path': 'm214-7h429v214h-429v-214z m500 0h72v500q0 8-6 21t-11 20l-157 156q-5 6-19 12t-22 5v-232q0-22-15-38t-38-16h-322q-22 0-37 16t-16 38v232h-72v-714h72v232q0 22 16 38t37 16h465q22 0 38-16t15-38v-232z m-214 518v178q0 8-5 13t-13 5h-107q-7 0-13-5t-5-13v-178q0-8 5-13t13-5h107q7 0 13 5t5 13z m357-18v-518q0-22-15-38t-38-16h-750q-23 0-38 16t-16 38v750q0 22 16 38t38 16h517q23 0 50-12t42-26l156-157q16-15 27-42t11-49z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'lasso': {
+ 'width': 1031,
+ 'height': 1000,
+ 'path': 'm1018 538c-36 207-290 336-568 286-277-48-473-256-436-463 10-57 36-108 76-151-13-66 11-137 68-183 34-28 75-41 114-42l-55-70 0 0c-2-1-3-2-4-3-10-14-8-34 5-45 14-11 34-8 45 4 1 1 2 3 2 5l0 0 113 140c16 11 31 24 45 40 4 3 6 7 8 11 48-3 100 0 151 9 278 48 473 255 436 462z m-624-379c-80 14-149 48-197 96 42 42 109 47 156 9 33-26 47-66 41-105z m-187-74c-19 16-33 37-39 60 50-32 109-55 174-68-42-25-95-24-135 8z m360 75c-34-7-69-9-102-8 8 62-16 128-68 170-73 59-175 54-244-5-9 20-16 40-20 61-28 159 121 317 333 354s407-60 434-217c28-159-121-318-333-355z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'selectbox': {
+ 'width': 1000,
+ 'height': 1000,
+ 'path': 'm0 850l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m285 0l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m-857-286l0-143 143 0 0 143-143 0z m857 0l0-143 143 0 0 143-143 0z m-857-285l0-143 143 0 0 143-143 0z m857 0l0-143 143 0 0 143-143 0z m-857-286l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m285 0l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z',
+ 'transform': 'matrix(1 0 0 -1 0 850)'
+ },
+ 'spikeline': {
+ 'width': 1000,
+ 'height': 1000,
+ 'path': 'M512 409c0-57-46-104-103-104-57 0-104 47-104 104 0 57 47 103 104 103 57 0 103-46 103-103z m-327-39l92 0 0 92-92 0z m-185 0l92 0 0 92-92 0z m370-186l92 0 0 93-92 0z m0-184l92 0 0 92-92 0z',
+ 'transform': 'matrix(1.5 0 0 -1.5 0 850)'
+ },
+ 'pencil': {
+ 'width': 1792,
+ 'height': 1792,
+ 'path': 'M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832h-416v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z',
+ 'transform': 'matrix(1 0 0 1 0 1)'
+ },
+ 'newplotlylogo': {
+ 'name': 'newplotlylogo',
+ 'svg': '
plotly-logomark '
+ }
+};
+
+},{}],154:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
'use strict';
@@ -34396,7 +34490,7 @@ exports.isBottomAnchor = function isBottomAnchor(opts) {
);
};
-},{}],154:[function(_dereq_,module,exports){
+},{}],155:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -34637,7 +34731,7 @@ module.exports = {
pathAnnulus: pathAnnulus
};
-},{"./mod":175}],155:[function(_dereq_,module,exports){
+},{"./mod":176}],156:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -34794,7 +34888,7 @@ function _rowLength(z, fn, len0) {
return 0;
}
-},{}],156:[function(_dereq_,module,exports){
+},{}],157:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -34827,7 +34921,7 @@ module.exports = function cleanNumber(v) {
return BADNUM;
};
-},{"../constants/numerical":149,"fast-isnumeric":18}],157:[function(_dereq_,module,exports){
+},{"../constants/numerical":149,"fast-isnumeric":18}],158:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -34855,7 +34949,7 @@ module.exports = function clearGlCanvases(gd) {
}
};
-},{}],158:[function(_dereq_,module,exports){
+},{}],159:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -34878,7 +34972,7 @@ module.exports = function clearResponsive(gd) {
}
};
-},{}],159:[function(_dereq_,module,exports){
+},{}],160:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -35342,7 +35436,7 @@ function validate(value, opts) {
}
exports.validate = validate;
-},{"../components/colorscale/scales":66,"../constants/interactions":148,"../plots/attributes":209,"./array":155,"./mod":175,"./nested_property":176,"./regex":183,"fast-isnumeric":18,"tinycolor2":34}],160:[function(_dereq_,module,exports){
+},{"../components/colorscale/scales":66,"../constants/interactions":148,"../plots/attributes":210,"./array":156,"./mod":176,"./nested_property":177,"./regex":184,"fast-isnumeric":18,"tinycolor2":34}],161:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -35928,7 +36022,110 @@ exports.findExactDates = function(data, calendar) {
};
};
-},{"../constants/numerical":149,"../registry":256,"./loggers":172,"./mod":175,"d3":16,"fast-isnumeric":18}],161:[function(_dereq_,module,exports){
+},{"../constants/numerical":149,"../registry":258,"./loggers":173,"./mod":176,"d3":16,"fast-isnumeric":18}],162:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+var d3 = _dereq_('d3');
+var loggers = _dereq_('./loggers');
+
+/**
+ * Allow referencing a graph DOM element either directly
+ * or by its id string
+ *
+ * @param {HTMLDivElement|string} gd: a graph element or its id
+ *
+ * @returns {HTMLDivElement} the DOM element of the graph
+ */
+function getGraphDiv(gd) {
+ var gdElement;
+
+ if(typeof gd === 'string') {
+ gdElement = document.getElementById(gd);
+
+ if(gdElement === null) {
+ throw new Error('No DOM element with id \'' + gd + '\' exists on the page.');
+ }
+
+ return gdElement;
+ } else if(gd === null || gd === undefined) {
+ throw new Error('DOM element provided is null or undefined');
+ }
+
+ // otherwise assume that gd is a DOM element
+ return gd;
+}
+
+function isPlotDiv(el) {
+ var el3 = d3.select(el);
+ return el3.node() instanceof HTMLElement &&
+ el3.size() &&
+ el3.classed('js-plotly-plot');
+}
+
+function removeElement(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
+ */
+function addStyleRule(selector, styleString) {
+ addRelatedStyleRule('global', selector, styleString);
+}
+
+/**
+ * for dynamically adding style rules
+ * to a stylesheet uniquely identified by a uid
+ */
+function addRelatedStyleRule(uid, selector, styleString) {
+ var id = 'plotly.js-style-' + uid;
+ var style = document.getElementById(id);
+ if(!style) {
+ style = document.createElement('style');
+ style.setAttribute('id', id);
+ // WebKit hack :(
+ style.appendChild(document.createTextNode(''));
+ document.head.appendChild(style);
+ }
+ var styleSheet = style.sheet;
+
+ if(styleSheet.insertRule) {
+ styleSheet.insertRule(selector + '{' + styleString + '}', 0);
+ } else if(styleSheet.addRule) {
+ styleSheet.addRule(selector, styleString, 0);
+ } else loggers.warn('addStyleRule failed');
+}
+
+/**
+ * to remove from the page a stylesheet identified by a given uid
+ */
+function deleteRelatedStyleRule(uid) {
+ var id = 'plotly.js-style-' + uid;
+ var style = document.getElementById(id);
+ if(style) removeElement(style);
+}
+
+module.exports = {
+ getGraphDiv: getGraphDiv,
+ isPlotDiv: isPlotDiv,
+ removeElement: removeElement,
+ addStyleRule: addStyleRule,
+ addRelatedStyleRule: addRelatedStyleRule,
+ deleteRelatedStyleRule: deleteRelatedStyleRule
+};
+
+},{"./loggers":173,"d3":16}],163:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -36101,7 +36298,7 @@ var Events = {
module.exports = Events;
-},{"events":15}],162:[function(_dereq_,module,exports){
+},{"events":15}],164:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -36215,7 +36412,7 @@ function _extend(inputs, isDeep, keepAllKeys, noArrayCopies) {
return target;
}
-},{"./is_plain_object.js":169}],163:[function(_dereq_,module,exports){
+},{"./is_plain_object.js":170}],165:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -36266,7 +36463,7 @@ module.exports = function filterUnique(array) {
return out;
};
-},{}],164:[function(_dereq_,module,exports){
+},{}],166:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -36314,7 +36511,7 @@ function isCalcData(cont) {
);
}
-},{}],165:[function(_dereq_,module,exports){
+},{}],167:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -36558,44 +36755,7 @@ exports.findPointOnPath = function findPointOnPath(path, val, coord, opts) {
return pt;
};
-},{"./mod":175}],166:[function(_dereq_,module,exports){
-/**
-* Copyright 2012-2019, 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.
-*/
-
-'use strict';
-
-/**
- * Allow referencing a graph DOM element either directly
- * or by its id string
- *
- * @param {HTMLDivElement|string} gd: a graph element or its id
- *
- * @returns {HTMLDivElement} the DOM element of the graph
- */
-module.exports = function(gd) {
- var gdElement;
-
- if(typeof gd === 'string') {
- gdElement = document.getElementById(gd);
-
- if(gdElement === null) {
- throw new Error('No DOM element with id \'' + gd + '\' exists on the page.');
- }
-
- return gdElement;
- } else if(gd === null || gd === undefined) {
- throw new Error('DOM element provided is null or undefined');
- }
-
- return gd; // otherwise assume that gd is a DOM element
-};
-
-},{}],167:[function(_dereq_,module,exports){
+},{"./mod":176}],168:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -36611,7 +36771,7 @@ module.exports = function(gd) {
module.exports = function identity(d) { return d; };
-},{}],168:[function(_dereq_,module,exports){
+},{}],169:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -36620,7 +36780,6 @@ module.exports = function identity(d) { return d; };
* LICENSE file in the root directory of this source tree.
*/
-
'use strict';
var d3 = _dereq_('d3');
@@ -36752,7 +36911,13 @@ lib.throttle = throttleModule.throttle;
lib.throttleDone = throttleModule.done;
lib.clearThrottle = throttleModule.clear;
-lib.getGraphDiv = _dereq_('./get_graph_div');
+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');
@@ -37068,13 +37233,25 @@ lib.noneOrAll = function(containerIn, containerOut, attrList) {
* @param {object} cd : calcdata trace
* @param {string} cdAttr : calcdata key
*/
-lib.mergeArray = function(traceAttr, cd, cdAttr) {
+lib.mergeArray = function(traceAttr, cd, cdAttr, fn) {
+ var hasFn = typeof fn === 'function';
if(lib.isArrayOrTypedArray(traceAttr)) {
var imax = Math.min(traceAttr.length, cd.length);
- for(var i = 0; i < imax; i++) cd[i][cdAttr] = traceAttr[i];
+ for(var i = 0; i < imax; i++) {
+ var v = traceAttr[i];
+ cd[i][cdAttr] = hasFn ? fn(v) : v;
+ }
}
};
+// cast numbers to positive numbers, returns 0 if not greater than 0
+lib.mergeArrayCastPositive = function(traceAttr, cd, cdAttr) {
+ return lib.mergeArray(traceAttr, cd, cdAttr, function(v) {
+ var w = +v;
+ return !isFinite(w) ? 0 : w > 0 ? w : 0;
+ });
+};
+
/** fills calcdata field (given by cdAttr) with traceAttr values
* or function of traceAttr values (e.g. some fallback)
*
@@ -37263,6 +37440,8 @@ lib.minExtend = function(obj1, obj2) {
} else {
objOut[k] = v.slice(0, arrayLen);
}
+ } else if(lib.isTypedArray(v)) {
+ objOut[k] = v.subarray(0, arrayLen);
} else if(v && (typeof v === 'object')) objOut[k] = lib.minExtend(obj1[k], obj2[k]);
else objOut[k] = v;
}
@@ -37290,63 +37469,20 @@ lib.containsAny = function(s, fragments) {
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) {
- lib.addRelatedStyleRule('global', selector, styleString);
-};
-
-/**
- * for dynamically adding style rules
- * to a stylesheet uniquely identified by a uid
- */
-lib.addRelatedStyleRule = function(uid, selector, styleString) {
- var id = 'plotly.js-style-' + uid;
- var style = document.getElementById(id);
- if(!style) {
- style = document.createElement('style');
- style.setAttribute('id', id);
- // WebKit hack :(
- style.appendChild(document.createTextNode(''));
- document.head.appendChild(style);
- }
- var styleSheet = style.sheet;
-
- if(styleSheet.insertRule) {
- styleSheet.insertRule(selector + '{' + styleString + '}', 0);
- } else if(styleSheet.addRule) {
- styleSheet.addRule(selector, styleString, 0);
- } else lib.warn('addStyleRule failed');
-};
-
-/**
- * to remove from the page a stylesheet identified by a given uid
- */
-lib.deleteRelatedStyleRule = function(uid) {
- var id = 'plotly.js-style-' + uid;
- var style = document.getElementById(id);
- if(style) lib.removeElement(style);
-};
-
lib.isIE = function() {
return typeof window.navigator.msSaveBlob !== 'undefined';
};
+var IS_IE9_OR_BELOW_REGEX = /MSIE [1-9]\./;
+lib.isIE9orBelow = function() {
+ return lib.isIE() && IS_IE9_OR_BELOW_REGEX.test(window.navigator.userAgent);
+};
+
+var IS_SAFARI_REGEX = /Version\/[\d\.]+.*Safari/;
+lib.isSafari = function() {
+ return IS_SAFARI_REGEX.test(window.navigator.userAgent);
+};
+
/**
* Duck typing to recognize a d3 selection, mostly for IE9's benefit
* because it doesn't handle instanceof like modern browsers
@@ -37604,7 +37740,7 @@ lib.numSeparate = function(value, separators, separatethousands) {
return x1 + x2;
};
-lib.TEMPLATE_STRING_REGEX = /%{([^\s%{}:]*)(:[^}]*)?}/g;
+lib.TEMPLATE_STRING_REGEX = /%{([^\s%{}:]*)([:|\|][^}]*)?}/g;
var SIMPLE_PROPERTY_REGEX = /^\w*$/;
/**
@@ -37633,9 +37769,25 @@ lib.templateString = function(string, obj) {
});
};
-var TEMPLATE_STRING_FORMAT_SEPARATOR = /^:/;
-var numberOfHoverTemplateWarnings = 0;
-var maximumNumberOfHoverTemplateWarnings = 10;
+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 = /^[:|\|]/;
/**
* Substitute values from an object into a string and optionally formats them using d3-format,
* or fallback to associated labels.
@@ -37645,15 +37797,17 @@ var maximumNumberOfHoverTemplateWarnings = 10;
* Lib.hovertemplateString('name: %{trace[0].name}', {trace: [{name: 'asdf'}]}) --> 'name: asdf'
* Lib.hovertemplateString('price: %{y:$.2f}', {y: 1}) --> 'price: $1.00'
*
- * @param {obj} d3 locale
* @param {string} input string containing %{...:...} template strings
* @param {obj} data object containing fallback text when no formatting is specified, ex.: {yLabel: 'formattedYValue'}
+ * @param {obj} d3 locale
* @param {obj} data objects containing substitution values
*
* @return {string} templated string
*/
-lib.hovertemplateString = function(string, labels, d3locale) {
+function templateFormatString(string, labels, d3locale) {
+ var opts = this;
var args = arguments;
+ if(!labels) labels = {};
// Not all that useful, but cache nestedProperty instantiation
// just in case it speeds things up *slightly*:
var getterCache = {};
@@ -37662,6 +37816,7 @@ lib.hovertemplateString = function(string, labels, d3locale) {
var obj, value, i;
for(i = 3; i < args.length; i++) {
obj = args[i];
+ if(!obj) continue;
if(obj.hasOwnProperty(key)) {
value = obj[key];
break;
@@ -37674,32 +37829,38 @@ lib.hovertemplateString = function(string, labels, d3locale) {
if(value !== undefined) break;
}
- if(value === undefined) {
- if(numberOfHoverTemplateWarnings < maximumNumberOfHoverTemplateWarnings) {
- lib.warn('Variable \'' + key + '\' in hovertemplate could not be found!');
+ if(value === undefined && opts) {
+ if(opts.count < opts.max) {
+ lib.warn('Variable \'' + key + '\' in ' + opts.name + ' could not be found!');
value = match;
}
- if(numberOfHoverTemplateWarnings === maximumNumberOfHoverTemplateWarnings) {
- lib.warn('Too many hovertemplate warnings - additional warnings will be suppressed');
+ if(opts.count === opts.max) {
+ lib.warn('Too many ' + opts.name + ' warnings - additional warnings will be suppressed');
}
- numberOfHoverTemplateWarnings++;
+ opts.count++;
+
+ return match;
}
if(format) {
var fmt;
- if(d3locale) {
- fmt = d3locale.numberFormat;
- } else {
- fmt = d3.format;
+ if(format[0] === ':') {
+ fmt = d3locale ? d3locale.numberFormat : d3.format;
+ value = fmt(format.replace(TEMPLATE_STRING_FORMAT_SEPARATOR, ''))(value);
+ }
+
+ if(format[0] === '|') {
+ fmt = d3locale ? d3locale.timeFormat.utc : d3.time.format.utc;
+ var ms = lib.dateTime2ms(value);
+ value = lib.formatDate(ms, format.replace(TEMPLATE_STRING_FORMAT_SEPARATOR, ''), false, fmt);
}
- value = fmt(format.replace(TEMPLATE_STRING_FORMAT_SEPARATOR, ''))(value);
} else {
if(labels.hasOwnProperty(key + 'Label')) value = labels[key + 'Label'];
}
return value;
});
-};
+}
/*
* alphanumeric string sort, tailored for subplot IDs like scene2, scene10, x10y13 etc
@@ -37774,6 +37935,10 @@ lib.isValidTextValue = function(v) {
return v || v === 0;
};
+/**
+ * @param {number} ratio
+ * @param {number} n (number of decimal places)
+ */
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) + '%';
@@ -37786,7 +37951,41 @@ lib.formatPercent = function(ratio, n) {
return str;
};
-},{"../constants/numerical":149,"./anchor_utils":153,"./angles":154,"./array":155,"./clean_number":156,"./clear_responsive":158,"./coerce":159,"./dates":160,"./extend":162,"./filter_unique":163,"./filter_visible":164,"./geometry2d":165,"./get_graph_div":166,"./identity":167,"./is_plain_object":169,"./keyed_container":170,"./localize":171,"./loggers":172,"./make_trace_groups":173,"./matrix":174,"./mod":175,"./nested_property":176,"./noop":177,"./notifier":178,"./push_unique":181,"./regex":183,"./relative_attr":184,"./relink_private":185,"./search":186,"./stats":188,"./throttle":190,"./to_log_range":191,"d3":16,"fast-isnumeric":18}],169:[function(_dereq_,module,exports){
+lib.isHidden = function(gd) {
+ var display = window.getComputedStyle(gd).display;
+ return !display || display === 'none';
+};
+
+lib.getTextTransform = function(opts) {
+ var textX = opts.textX;
+ var textY = opts.textY;
+ var targetX = opts.targetX;
+ var targetY = opts.targetY;
+ var scale = opts.scale;
+ var rotate = opts.rotate;
+
+ var transformScale;
+ var transformRotate;
+ var transformTranslate;
+
+ if(scale < 1) transformScale = 'scale(' + scale + ') ';
+ else {
+ scale = 1;
+ transformScale = '';
+ }
+
+ transformRotate = (rotate) ?
+ 'rotate(' + rotate + ' ' + textX + ' ' + textY + ') ' : '';
+
+ // Note that scaling also affects the center of the text box
+ var translateX = (targetX - scale * textX);
+ var translateY = (targetY - scale * textY);
+ transformTranslate = 'translate(' + translateX + ' ' + translateY + ')';
+
+ return transformTranslate + transformScale + transformRotate;
+};
+
+},{"../constants/numerical":149,"./anchor_utils":154,"./angles":155,"./array":156,"./clean_number":157,"./clear_responsive":159,"./coerce":160,"./dates":161,"./dom":162,"./extend":164,"./filter_unique":165,"./filter_visible":166,"./geometry2d":167,"./identity":168,"./is_plain_object":170,"./keyed_container":171,"./localize":172,"./loggers":173,"./make_trace_groups":174,"./matrix":175,"./mod":176,"./nested_property":177,"./noop":178,"./notifier":179,"./push_unique":182,"./regex":184,"./relative_attr":185,"./relink_private":186,"./search":187,"./stats":189,"./throttle":191,"./to_log_range":192,"d3":16,"fast-isnumeric":18}],170:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -37814,7 +38013,7 @@ module.exports = function isPlainObject(obj) {
);
};
-},{}],170:[function(_dereq_,module,exports){
+},{}],171:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -38007,7 +38206,7 @@ module.exports = function keyedContainer(baseObj, path, keyName, valueName) {
return obj;
};
-},{"./nested_property":176}],171:[function(_dereq_,module,exports){
+},{"./nested_property":177}],172:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -38063,7 +38262,7 @@ module.exports = function localize(gd, s) {
return s;
};
-},{"../registry":256}],172:[function(_dereq_,module,exports){
+},{"../registry":258}],173:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -38147,7 +38346,7 @@ function apply(f, args) {
}
}
-},{"../plot_api/plot_config":200}],173:[function(_dereq_,module,exports){
+},{"../plot_api/plot_config":201}],174:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -38156,9 +38355,10 @@ function apply(f, args) {
* LICENSE file in the root directory of this source tree.
*/
-
'use strict';
+var d3 = _dereq_('d3');
+
/**
* General helper to manage trace groups based on calcdata
*
@@ -38181,10 +38381,15 @@ module.exports = function makeTraceGroups(traceLayer, cdModule, cls) {
traces.order();
+ // stash ref node to trace group in calcdata,
+ // useful for (fast) styleOnSelect
+ var k = traceLayer.classed('rangeplot') ? 'nodeRangePlot3' : 'node3';
+ traces.each(function(cd) { cd[0][k] = d3.select(this); });
+
return traces;
};
-},{}],174:[function(_dereq_,module,exports){
+},{"d3":16}],175:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -38291,7 +38496,7 @@ exports.apply2DTransform2 = function(transform) {
};
};
-},{}],175:[function(_dereq_,module,exports){
+},{}],176:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -38326,7 +38531,7 @@ module.exports = {
modHalf: modHalf
};
-},{}],176:[function(_dereq_,module,exports){
+},{}],177:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -38572,7 +38777,7 @@ function badContainer(container, propStr, propParts) {
};
}
-},{"./array":155,"fast-isnumeric":18}],177:[function(_dereq_,module,exports){
+},{"./array":156,"fast-isnumeric":18}],178:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -38588,7 +38793,7 @@ function badContainer(container, propStr, propParts) {
module.exports = function noop() {};
-},{}],178:[function(_dereq_,module,exports){
+},{}],179:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -38670,7 +38875,7 @@ module.exports = function(text, displayLength) {
});
};
-},{"d3":16,"fast-isnumeric":18}],179:[function(_dereq_,module,exports){
+},{"d3":16,"fast-isnumeric":18}],180:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -38718,7 +38923,7 @@ module.exports = function overrideCursor(el3, csr) {
}
};
-},{"./setcursor":187}],180:[function(_dereq_,module,exports){
+},{"./setcursor":188}],181:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -38970,7 +39175,7 @@ polygon.filter = function filter(pts, tolerance) {
};
};
-},{"../constants/numerical":149,"./matrix":174}],181:[function(_dereq_,module,exports){
+},{"../constants/numerical":149,"./matrix":175}],182:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -39008,7 +39213,7 @@ module.exports = function pushUnique(array, item) {
return array;
};
-},{}],182:[function(_dereq_,module,exports){
+},{}],183:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -39216,7 +39421,7 @@ queue.plotDo = function(gd, func, args) {
module.exports = queue;
-},{"../lib":168,"../plot_api/plot_config":200}],183:[function(_dereq_,module,exports){
+},{"../lib":169,"../plot_api/plot_config":201}],184:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -39246,7 +39451,7 @@ exports.counter = function(head, tail, openEnded, matchBeginning) {
return new RegExp(startWithPrefix + head + '([2-9]|[1-9][0-9]+)?' + fullTail);
};
-},{}],184:[function(_dereq_,module,exports){
+},{}],185:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -39299,7 +39504,7 @@ module.exports = function(baseAttr, relativeAttr) {
return baseAttr + relativeAttr;
};
-},{}],185:[function(_dereq_,module,exports){
+},{}],186:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -39357,7 +39562,7 @@ module.exports = function relinkPrivateKeys(toContainer, fromContainer) {
}
};
-},{"./array":155,"./is_plain_object":169}],186:[function(_dereq_,module,exports){
+},{"./array":156,"./is_plain_object":170}],187:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -39544,7 +39749,7 @@ exports.findIndexOfMin = function(arr, fn) {
return ind;
};
-},{"./identity":167,"./loggers":172,"fast-isnumeric":18}],187:[function(_dereq_,module,exports){
+},{"./identity":168,"./loggers":173,"fast-isnumeric":18}],188:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -39567,7 +39772,7 @@ module.exports = function setCursor(el3, csr) {
if(csr) el3.classed('cursor-' + csr, true);
};
-},{}],188:[function(_dereq_,module,exports){
+},{}],189:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -39677,7 +39882,7 @@ exports.interp = function(arr, n) {
return frac * arr[Math.ceil(n)] + (1 - frac) * arr[Math.floor(n)];
};
-},{"./array":155,"fast-isnumeric":18}],189:[function(_dereq_,module,exports){
+},{"./array":156,"fast-isnumeric":18}],190:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -39939,13 +40144,14 @@ var ZERO_WIDTH_SPACE = '\u200b';
*/
var PROTOCOLS = ['http:', 'https:', 'mailto:', '', undefined, ':'];
-var NEWLINES = /(\r\n?|\n)/g;
+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;
/*
* style and href: pull them out of either single or double quotes. Also
@@ -40492,7 +40698,7 @@ exports.makeEditable = function(context, options) {
return d3.rebind(context, dispatch, 'on');
};
-},{"../constants/alignment":146,"../constants/xmlns_namespaces":150,"../lib":168,"d3":16}],190:[function(_dereq_,module,exports){
+},{"../constants/alignment":145,"../constants/xmlns_namespaces":150,"../lib":169,"d3":16}],191:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -40595,7 +40801,7 @@ function _clearTimeout(cache) {
}
}
-},{}],191:[function(_dereq_,module,exports){
+},{}],192:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -40623,7 +40829,7 @@ module.exports = function toLogRange(val, range) {
return newVal;
};
-},{"fast-isnumeric":18}],192:[function(_dereq_,module,exports){
+},{"fast-isnumeric":18}],193:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -40645,7 +40851,7 @@ module.exports = {
}
};
-},{}],193:[function(_dereq_,module,exports){
+},{}],194:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -40688,7 +40894,7 @@ module.exports = {
}
};
-},{}],194:[function(_dereq_,module,exports){
+},{}],195:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -40746,7 +40952,7 @@ module.exports = function containerArrayMatch(astr) {
return {array: arrayStr, index: Number(match[1]), property: match[3] || ''};
};
-},{"../registry":256}],195:[function(_dereq_,module,exports){
+},{"../registry":258}],196:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -40871,7 +41077,7 @@ function overrideOne(attr, editTypeOverride, overrideContainers, key) {
}
}
-},{"../lib":168}],196:[function(_dereq_,module,exports){
+},{"../lib":169}],197:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -41563,7 +41769,7 @@ exports.clearAxisTypes = function(gd, traces, layoutUpdate) {
}
};
-},{"../components/color":51,"../lib":168,"../plots/cartesian/axis_ids":215,"../plots/plots":244,"../registry":256,"fast-isnumeric":18,"gl-mat4/fromQuat":19}],197:[function(_dereq_,module,exports){
+},{"../components/color":51,"../lib":169,"../plots/cartesian/axis_ids":216,"../plots/plots":245,"../registry":258,"fast-isnumeric":18,"gl-mat4/fromQuat":19}],198:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -41606,7 +41812,7 @@ var templateApi = _dereq_('./template_api');
exports.makeTemplate = templateApi.makeTemplate;
exports.validateTemplate = templateApi.validateTemplate;
-},{"../snapshot/download":258,"./plot_api":199,"./template_api":204,"./to_image":205,"./validate":206}],198:[function(_dereq_,module,exports){
+},{"../snapshot/download":260,"./plot_api":200,"./template_api":205,"./to_image":206,"./validate":207}],199:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -41819,7 +42025,7 @@ exports.applyContainerArrayChanges = function applyContainerArrayChanges(gd, np,
return true;
};
-},{"../lib/is_plain_object":169,"../lib/loggers":172,"../lib/noop":177,"../lib/search":186,"../registry":256,"./container_array_match":194}],199:[function(_dereq_,module,exports){
+},{"../lib/is_plain_object":170,"../lib/loggers":173,"../lib/noop":178,"../lib/search":187,"../registry":258,"./container_array_match":195}],200:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -42004,7 +42210,7 @@ function plot(gd, data, layout, config) {
if(gd._context.responsive) {
if(!gd._responsiveChartHandler) {
// Keep a reference to the resize handler to purge it down the road
- gd._responsiveChartHandler = function() { Plots.resize(gd); };
+ gd._responsiveChartHandler = function() { if(!Lib.isHidden(gd)) Plots.resize(gd); };
// Listen to window resize
window.addEventListener('resize', gd._responsiveChartHandler);
@@ -42112,6 +42318,17 @@ function plot(gd, data, layout, config) {
subroutines.drawMarginPushers(gd);
Axes.allowAutoMargin(gd);
+ // TODO can this be moved elsewhere?
+ if(fullLayout._has('pie')) {
+ var fullData = gd._fullData;
+ for(var i = 0; i < fullData.length; i++) {
+ var trace = fullData[i];
+ if(trace.type === 'pie' && trace.automargin) {
+ Plots.allowAutoMargin(gd, 'pie.' + trace.uid + '.automargin');
+ }
+ }
+ }
+
Plots.doAutoMargin(gd);
return Plots.previousPromises(gd);
}
@@ -44272,7 +44489,7 @@ var traceUIControlPatterns = [
{pattern: /(^|value\.)visible$/, attr: 'legend.uirevision'},
{pattern: /^dimensions\[\d+\]\.constraintrange/},
{pattern: /^node\.(x|y|groups)/}, // for Sankey nodes
- {pattern: /^level$/}, // for Sunburst traces
+ {pattern: /^level$/}, // for Sunburst & Treemap traces
// below this you must be in editable: true mode
// TODO: I still put name and title with `trace.uirevision`
@@ -44479,6 +44696,7 @@ function react(gd, data, layout, config) {
function addFrames() { return exports.addFrames(gd, frames); }
gd = Lib.getGraphDiv(gd);
+ helpers.clearPromiseQueue(gd);
var oldFullData = gd._fullData;
var oldFullLayout = gd._fullLayout;
@@ -44633,7 +44851,11 @@ function diffData(gd, oldFullData, newFullData, immutable, transition, newDataRe
var i, trace;
function getTraceValObject(parts) {
- return PlotSchema.getTraceValObject(trace, parts);
+ var out = PlotSchema.getTraceValObject(trace, parts);
+ if(!trace._module.animatable && out.anim) {
+ out.anim = false;
+ }
+ return out;
}
var diffOpts = {
@@ -45442,7 +45664,7 @@ function deleteFrames(gd, frameList) {
}
}
- frameList = frameList.slice(0);
+ frameList = frameList.slice();
frameList.sort();
for(i = frameList.length - 1; i >= 0; i--) {
@@ -45598,9 +45820,15 @@ function makePlotFramework(gd) {
// single pie layer for the whole plot
fullLayout._pielayer = fullLayout._paper.append('g').classed('pielayer', true);
+ // single treemap layer for the whole plot
+ fullLayout._treemaplayer = fullLayout._paper.append('g').classed('treemaplayer', true);
+
// single sunburst layer for the whole plot
fullLayout._sunburstlayer = fullLayout._paper.append('g').classed('sunburstlayer', true);
+ // single indicator layer for the whole plot
+ fullLayout._indicatorlayer = fullLayout._toppaper.append('g').classed('indicatorlayer', true);
+
// fill in image server scrape-svg
fullLayout._glimages = fullLayout._paper.append('g').classed('glimages', true);
@@ -45659,7 +45887,7 @@ exports._guiUpdate = guiEdit(update);
exports._storeDirectGUIEdit = _storeDirectGUIEdit;
-},{"../components/color":51,"../components/drawing":72,"../constants/xmlns_namespaces":150,"../lib":168,"../lib/events":161,"../lib/queue":182,"../lib/svg_text_utils":189,"../plots/cartesian/axes":212,"../plots/cartesian/constants":218,"../plots/cartesian/graph_interact":221,"../plots/cartesian/select":229,"../plots/plots":244,"../plots/polar/legacy":247,"../registry":256,"./edit_types":195,"./helpers":196,"./manage_arrays":198,"./plot_config":200,"./plot_schema":201,"./subroutines":203,"d3":16,"fast-isnumeric":18,"has-hover":20}],200:[function(_dereq_,module,exports){
+},{"../components/color":51,"../components/drawing":72,"../constants/xmlns_namespaces":150,"../lib":169,"../lib/events":163,"../lib/queue":183,"../lib/svg_text_utils":190,"../plots/cartesian/axes":213,"../plots/cartesian/constants":219,"../plots/cartesian/graph_interact":222,"../plots/cartesian/select":230,"../plots/plots":245,"../plots/polar/legacy":248,"../registry":258,"./edit_types":196,"./helpers":197,"./manage_arrays":199,"./plot_config":201,"./plot_schema":202,"./subroutines":204,"d3":16,"fast-isnumeric":18,"has-hover":20}],201:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -45788,6 +46016,12 @@ var configAttributes = {
values: [false, 'reset', 'autosize', 'reset+autosize'],
dflt: 'reset+autosize',
+ },
+ doubleClickDelay: {
+ valType: 'number',
+ dflt: 300,
+ min: 0,
+
},
showAxisDragHandles: {
@@ -45839,6 +46073,11 @@ var configAttributes = {
valType: 'boolean',
dflt: false,
+ },
+ showEditInChartStudio: {
+ valType: 'boolean',
+ dflt: false,
+
},
modeBarButtonsToRemove: {
valType: 'any',
@@ -45953,7 +46192,7 @@ module.exports = {
dfltConfig: dfltConfig
};
-},{}],201:[function(_dereq_,module,exports){
+},{}],202:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -45962,7 +46201,6 @@ module.exports = {
* LICENSE file in the root directory of this source tree.
*/
-
'use strict';
var Registry = _dereq_('../registry');
@@ -46445,6 +46683,7 @@ function getTraceAttributes(type) {
var out = {
meta: _module.meta || {},
categories: _module.categories || {},
+ animatable: Boolean(_module.animatable),
type: type,
attributes: formatAttributes(attributes),
};
@@ -46457,6 +46696,15 @@ function getTraceAttributes(type) {
out.layoutAttributes = formatAttributes(layoutAttributes);
}
+ // drop anim:true in non-animatable modules
+ if(!_module.animatable) {
+ exports.crawl(out, function(attr) {
+ if(exports.isValObject(attr) && 'anim' in attr) {
+ delete attr.anim;
+ }
+ });
+ }
+
return out;
}
@@ -46655,7 +46903,7 @@ function insertAttrs(baseAttrs, newAttrs, astr) {
np.set(extendDeepAll(np.get() || {}, newAttrs));
}
-},{"../lib":168,"../plots/animation_attributes":207,"../plots/attributes":209,"../plots/frame_attributes":239,"../plots/layout_attributes":242,"../plots/polar/legacy/area_attributes":245,"../plots/polar/legacy/axis_attributes":246,"../registry":256,"./edit_types":195,"./plot_config":200}],202:[function(_dereq_,module,exports){
+},{"../lib":169,"../plots/animation_attributes":208,"../plots/attributes":210,"../plots/frame_attributes":240,"../plots/layout_attributes":243,"../plots/polar/legacy/area_attributes":246,"../plots/polar/legacy/axis_attributes":247,"../registry":258,"./edit_types":196,"./plot_config":201}],203:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -46967,7 +47215,7 @@ exports.arrayEditor = function(parentIn, containerStr, itemOut) {
};
};
-},{"../lib":168,"../plots/attributes":209}],203:[function(_dereq_,module,exports){
+},{"../lib":169,"../plots/attributes":210}],204:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -47042,7 +47290,7 @@ function lsInner(gd) {
// can still get here because it makes some of the SVG structure
// for shared features like selections.
if(!fullLayout._has('cartesian')) {
- return gd._promises.length && Promise.all(gd._promises);
+ return Plots.previousPromises(gd);
}
function getLinePosition(ax, counterAx, side) {
@@ -47317,7 +47565,7 @@ function lsInner(gd) {
Axes.makeClipPaths(gd);
- return gd._promises.length && Promise.all(gd._promises);
+ return Plots.previousPromises(gd);
}
function shouldShowLinesOrTicks(ax, subplot) {
@@ -47548,8 +47796,7 @@ exports.doCamera = function(gd) {
var sceneLayout = fullLayout[sceneIds[i]];
var scene = sceneLayout._scene;
- var cameraData = sceneLayout.camera;
- scene.setCamera(cameraData);
+ scene.setViewport(sceneLayout);
}
};
@@ -47569,9 +47816,11 @@ exports.drawData = function(gd) {
// styling separate from drawing
Plots.style(gd);
- // show annotations and shapes
+ // draw components that can be drawn on axes,
+ // and that do not push the margins
Registry.getComponentMethod('shapes', 'draw')(gd);
Registry.getComponentMethod('annotations', 'draw')(gd);
+ Registry.getComponentMethod('images', 'draw')(gd);
// Mark the first render as complete
fullLayout._replotting = false;
@@ -47687,9 +47936,6 @@ exports.doAutoRangeAndConstraints = function(gd) {
// correctly sized and the whole plot re-margined. fullLayout._replotting must
// be set to false before these will work properly.
exports.finalDraw = function(gd) {
- Registry.getComponentMethod('shapes', 'draw')(gd);
- Registry.getComponentMethod('images', 'draw')(gd);
- Registry.getComponentMethod('annotations', 'draw')(gd);
// TODO: rangesliders really belong in marginPushers but they need to be
// drawn after data - can we at least get the margin pushing part separated
// out and done earlier?
@@ -47709,7 +47955,7 @@ exports.drawMarginPushers = function(gd) {
Registry.getComponentMethod('colorbar', 'draw')(gd);
};
-},{"../components/color":51,"../components/drawing":72,"../components/modebar":110,"../components/titles":139,"../constants/alignment":146,"../lib":168,"../lib/clear_gl_canvases":157,"../plots/cartesian/autorange":211,"../plots/cartesian/axes":212,"../plots/cartesian/constraints":219,"../plots/plots":244,"../registry":256,"d3":16}],204:[function(_dereq_,module,exports){
+},{"../components/color":51,"../components/drawing":72,"../components/modebar":109,"../components/titles":138,"../constants/alignment":145,"../lib":169,"../lib/clear_gl_canvases":158,"../plots/cartesian/autorange":212,"../plots/cartesian/axes":213,"../plots/cartesian/constraints":220,"../plots/plots":245,"../registry":258,"d3":16}],205:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -48171,7 +48417,7 @@ function format(opts) {
return opts;
}
-},{"../lib":168,"../plots/attributes":209,"../plots/plots":244,"./plot_config":200,"./plot_schema":201,"./plot_template":202}],205:[function(_dereq_,module,exports){
+},{"../lib":169,"../plots/attributes":210,"../plots/plots":245,"./plot_config":201,"./plot_schema":202,"./plot_template":203}],206:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -48226,8 +48472,6 @@ var attrs = {
}
};
-var IMAGE_URL_PREFIX = /^data:image\/\w+;base64,/;
-
/** Plotly.toImage
*
* @param {object | string | HTML div} gd
@@ -48331,7 +48575,7 @@ function toImage(gd, opts) {
if(imageDataOnly) {
return resolve(svg);
} else {
- return resolve('data:image/svg+xml,' + encodeURIComponent(svg));
+ return resolve(helpers.encodeSVG(svg));
}
}
@@ -48358,7 +48602,7 @@ function toImage(gd, opts) {
function urlToImageData(url) {
if(imageDataOnly) {
- return url.replace(IMAGE_URL_PREFIX, '');
+ return url.replace(helpers.IMAGE_URL_PREFIX, '');
} else {
return url;
}
@@ -48376,7 +48620,7 @@ function toImage(gd, opts) {
module.exports = toImage;
-},{"../lib":168,"../snapshot/helpers":260,"../snapshot/svgtoimg":262,"../snapshot/tosvg":264,"./plot_api":199,"fast-isnumeric":18}],206:[function(_dereq_,module,exports){
+},{"../lib":169,"../snapshot/helpers":262,"../snapshot/svgtoimg":264,"../snapshot/tosvg":266,"./plot_api":200,"fast-isnumeric":18}],207:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -48803,7 +49047,7 @@ function convertPathToAttributeString(path) {
return astr;
}
-},{"../lib":168,"../plots/plots":244,"./plot_config":200,"./plot_schema":201}],207:[function(_dereq_,module,exports){
+},{"../lib":169,"../plots/plots":245,"./plot_config":201,"./plot_schema":202}],208:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -48915,7 +49159,7 @@ module.exports = {
}
};
-},{}],208:[function(_dereq_,module,exports){
+},{}],209:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -49010,7 +49254,7 @@ module.exports = function handleArrayContainerDefaults(parentObjIn, parentObjOut
return contOut;
};
-},{"../lib":168,"../plot_api/plot_template":202}],209:[function(_dereq_,module,exports){
+},{"../lib":169,"../plot_api/plot_template":203}],210:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -49151,7 +49395,7 @@ module.exports = {
}
};
-},{"../components/fx/attributes":81}],210:[function(_dereq_,module,exports){
+},{"../components/fx/attributes":81}],211:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -49180,7 +49424,7 @@ module.exports = {
}
};
-},{}],211:[function(_dereq_,module,exports){
+},{}],212:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -49481,6 +49725,8 @@ function doAutoRange(gd, ax) {
* (unless one end is overridden by tozero)
* tozero: (boolean) make sure to include zero if axis is linear,
* and make it a tight bound if possible
+ * vpadLinearized: (boolean) whether or not vpad (or vpadplus/vpadminus)
+ * is linearized (for log scale axes)
*
* @return {object}
* - min {array of objects}
@@ -49503,6 +49749,7 @@ function findExtremes(ax, data, opts) {
var tozero = opts.tozero && (ax.type === 'linear' || ax.type === '-');
var isLog = ax.type === 'log';
var hasArrayOption = false;
+ var vpadLinearized = opts.vpadLinearized || false;
var i, v, di, dmin, dmax, ppadiplus, ppadiminus, vmin, vmax;
function makePadAccessor(item) {
@@ -49554,16 +49801,22 @@ function findExtremes(ax, data, opts) {
if(!isNumeric(di)) return;
ppadiplus = ppadplus(i);
ppadiminus = ppadminus(i);
- vmin = di - vpadminus(i);
- vmax = di + vpadplus(i);
- // special case for log axes: if vpad makes this object span
- // more than an order of mag, clip it to one order. This is so
- // we don't have non-positive errors or absurdly large lower
- // range due to rounding errors
- if(isLog && vmin < vmax / 10) vmin = vmax / 10;
- dmin = ax.c2l(vmin);
- dmax = ax.c2l(vmax);
+ if(vpadLinearized) {
+ dmin = ax.c2l(di) - vpadminus(i);
+ dmax = ax.c2l(di) + vpadplus(i);
+ } else {
+ vmin = di - vpadminus(i);
+ vmax = di + vpadplus(i);
+ // special case for log axes: if vpad makes this object span
+ // more than an order of mag, clip it to one order. This is so
+ // we don't have non-positive errors or absurdly large lower
+ // range due to rounding errors
+ if(isLog && vmin < vmax / 10) vmin = vmax / 10;
+
+ dmin = ax.c2l(vmin);
+ dmax = ax.c2l(vmax);
+ }
if(tozero) {
dmin = Math.min(0, dmin);
@@ -49670,7 +49923,7 @@ function goodNumber(v) {
function lessOrEqual(v0, v1) { return v0 <= v1; }
function greaterOrEqual(v0, v1) { return v0 >= v1; }
-},{"../../constants/numerical":149,"../../lib":168,"../../registry":256,"fast-isnumeric":18}],212:[function(_dereq_,module,exports){
+},{"../../constants/numerical":149,"../../lib":169,"../../registry":258,"fast-isnumeric":18}],213:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -49679,7 +49932,6 @@ function greaterOrEqual(v0, v1) { return v0 >= v1; }
* LICENSE file in the root directory of this source tree.
*/
-
'use strict';
var d3 = _dereq_('d3');
@@ -49706,8 +49958,11 @@ var ONESEC = constants.ONESEC;
var MINUS_SIGN = constants.MINUS_SIGN;
var BADNUM = constants.BADNUM;
-var MID_SHIFT = _dereq_('../../constants/alignment').MID_SHIFT;
-var LINE_SPACING = _dereq_('../../constants/alignment').LINE_SPACING;
+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 = {};
@@ -50244,12 +50499,14 @@ axes.calcTicks = function calcTicks(ax) {
if((ax._tmin < startTick) !== axrev) return [];
// return the full set of tick vals
- var vals = [];
+ var tickVals = [];
if(ax.type === 'category' || ax.type === 'multicategory') {
endTick = (axrev) ? Math.max(-0.5, endTick) :
Math.min(ax._categories.length - 0.5, endTick);
}
+ var isDLog = (ax.type === 'log') && !(isNumeric(ax.dtick) || ax.dtick.charAt(0) === 'L');
+
var xPrevious = null;
var maxTicks = Math.max(1000, ax._length || 0);
for(var x = ax._tmin;
@@ -50257,21 +50514,29 @@ axes.calcTicks = function calcTicks(ax) {
x = axes.tickIncrement(x, ax.dtick, axrev, ax.calendar)) {
// prevent infinite loops - no more than one tick per pixel,
// and make sure each value is different from the previous
- if(vals.length > maxTicks || x === xPrevious) break;
+ if(tickVals.length > maxTicks || x === xPrevious) break;
xPrevious = x;
- vals.push(x);
+ var minor = false;
+ if(isDLog && (x !== (x | 0))) {
+ minor = true;
+ }
+
+ tickVals.push({
+ minor: minor,
+ value: x
+ });
}
// If same angle over a full circle, the last tick vals is a duplicate.
// TODO must do something similar for angular date axes.
if(isAngular(ax) && Math.abs(rng[1] - rng[0]) === 360) {
- vals.pop();
+ tickVals.pop();
}
// save the last tick as well as first, so we can
// show the exponent only on the last one
- ax._tmax = vals[vals.length - 1];
+ ax._tmax = (tickVals[tickVals.length - 1] || {}).value;
// for showing the rest of a date when the main tick label is only the
// latter part: ax._prevDateHead holds what we showed most recently.
@@ -50280,8 +50545,15 @@ axes.calcTicks = function calcTicks(ax) {
ax._prevDateHead = '';
ax._inCalcTicks = true;
- var ticksOut = new Array(vals.length);
- for(var i = 0; i < vals.length; i++) ticksOut[i] = axes.tickText(ax, vals[i]);
+ var ticksOut = new Array(tickVals.length);
+ for(var i = 0; i < tickVals.length; i++) {
+ ticksOut[i] = axes.tickText(
+ ax,
+ tickVals[i].value,
+ false, // hover
+ tickVals[i].minor // noSuffixPrefix
+ );
+ }
ax._inCalcTicks = false;
@@ -50496,7 +50768,6 @@ function autoTickRound(ax) {
ax._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)) {
@@ -50610,7 +50881,7 @@ axes.tickFirst = function(ax) {
// ax is the axis layout, x is the tick value
// hover is a (truthy) flag for whether to show numbers with a bit
// more precision for hovertext
-axes.tickText = function(ax, x, hover) {
+axes.tickText = function(ax, x, hover, noSuffixPrefix) {
var out = tickTextObj(ax, x);
var arrayMode = ax.tickmode === 'array';
var extraPrecision = hover || arrayMode;
@@ -50656,8 +50927,10 @@ axes.tickText = function(ax, x, hover) {
else formatLinear(ax, out, hover, extraPrecision, hideexp);
// add prefix and suffix
- if(ax.tickprefix && !isHidden(ax.showtickprefix)) out.text = ax.tickprefix + out.text;
- if(ax.ticksuffix && !isHidden(ax.showticksuffix)) out.text += ax.ticksuffix;
+ if(!noSuffixPrefix) {
+ if(ax.tickprefix && !isHidden(ax.showtickprefix)) out.text = ax.tickprefix + out.text;
+ if(ax.ticksuffix && !isHidden(ax.showticksuffix)) out.text += ax.ticksuffix;
+ }
// Setup ticks and grid lines boundaries
// at 1/2 a 'category' to the left/bottom
@@ -51291,6 +51564,25 @@ axes.draw = function(gd, arg, opts) {
* @param {object} ax (full) axis object
* @param {object} opts
* - @param {boolean} skipTitle (set to true to skip axis title draw call)
+ *
+ * Depends on:
+ * - ax._mainSubplot (from linkSubplots)
+ * - ax._mainAxis
+ * - ax._anchorAxis
+ * - ax._subplotsWith
+ * - ax._counterDomainMin, ax._counterDomainMax (optionally, from linkSubplots)
+ * - ax._tickAngles (on redraw only, old value relinked during supplyDefaults)
+ * - ax._mainLinePosition (from lsInner)
+ * - ax._mainMirrorPosition
+ * - ax._linepositions
+ *
+ * Fills in:
+ * - ax._vals:
+ * - ax._gridVals:
+ * - ax._selections:
+ * - ax._tickAngles:
+ * - ax._depth (when required only):
+ * - and calls ax.setScale
*/
axes.drawOne = function(gd, ax, opts) {
opts = opts || {};
@@ -51303,12 +51595,10 @@ axes.drawOne = function(gd, ax, opts) {
var axId = ax._id;
var axLetter = axId.charAt(0);
var counterLetter = axes.counterLetter(axId);
- var mainSubplot = ax._mainSubplot;
var mainLinePosition = ax._mainLinePosition;
var mainMirrorPosition = ax._mainMirrorPosition;
- var mainPlotinfo = fullLayout._plots[mainSubplot];
+ var mainPlotinfo = fullLayout._plots[ax._mainSubplot];
var mainAxLayer = mainPlotinfo[axLetter + 'axislayer'];
- var subplotsWithAx = ax._subplotsWith;
var vals = ax._vals = axes.calcTicks(ax);
@@ -51319,13 +51609,29 @@ axes.drawOne = function(gd, ax, opts) {
vals[i].axInfo = axInfo;
}
- if(!ax.visible) return;
-
// stash selections to avoid DOM queries e.g.
// - stash tickLabels selection, so that drawTitle can use it to scoot title
ax._selections = {};
// stash tick angle (including the computed 'auto' values) per tick-label class
+ // linkup 'previous' tick angles on redraws
+ if(ax._tickAngles) ax._prevTickAngles = ax._tickAngles;
ax._tickAngles = {};
+ // measure [in px] between axis position and outward-most part of bounding box
+ // (touching either the tick label or ticks)
+ // depth can be expansive to compute, so we only do so when required
+ ax._depth = null;
+
+ // calcLabelLevelBbox can be expensive,
+ // so make sure to not call it twice during the same Axes.drawOne call
+ // by stashing label-level bounding boxes per tick-label class
+ var llbboxes = {};
+ function getLabelLevelBbox(suffix) {
+ var cls = axId + (suffix || 'tick');
+ if(!llbboxes[cls]) llbboxes[cls] = calcLabelLevelBbox(ax, cls);
+ return llbboxes[cls];
+ }
+
+ if(!ax.visible) return;
var transFn = axes.makeTransFn(ax);
var tickVals;
@@ -51346,7 +51652,9 @@ axes.drawOne = function(gd, ax, opts) {
var dividerVals = getDividerVals(ax, vals);
if(!fullLayout._hasOnlyLargeSploms) {
- // keep track of which subplots (by main conteraxis) we've already
+ var subplotsWithAx = ax._subplotsWith;
+
+ // keep track of which subplots (by main counter axis) we've already
// drawn grids for, so we don't overdraw overlaying subplots
var finishedGrids = {};
@@ -51414,7 +51722,9 @@ axes.drawOne = function(gd, ax, opts) {
transFn: transFn
});
- tickSubplots = Object.keys(ax._linepositions || {});
+ if(ax.mirror === 'allticks') {
+ tickSubplots = Object.keys(ax._linepositions || {});
+ }
}
for(i = 0; i < tickSubplots.length; i++) {
@@ -51448,13 +51758,12 @@ axes.drawOne = function(gd, ax, opts) {
});
if(ax.type === 'multicategory') {
- var labelLength = 0;
var pad = {x: 2, y: 10}[axLetter];
- var sgn = tickSigns[2] * (ax.ticks === 'inside' ? -1 : 1);
seq.push(function() {
- labelLength += getLabelLevelSpan(ax, axId + 'tick') + pad;
- labelLength += ax._tickAngles[axId + 'tick'] ? ax.tickfont.size * LINE_SPACING : 0;
+ var bboxKey = {x: 'height', y: 'width'}[axLetter];
+ var standoff = getLabelLevelBbox()[bboxKey] + pad +
+ (ax._tickAngles[axId + 'tick'] ? ax.tickfont.size * LINE_SPACING : 0);
return axes.drawLabels(gd, ax, {
vals: getSecondaryLabelVals(ax, vals),
@@ -51463,197 +51772,129 @@ axes.drawOne = function(gd, ax, opts) {
repositionOnUpdate: true,
secondary: true,
transFn: transFn,
- labelFns: axes.makeLabelFns(ax, mainLinePosition + labelLength * sgn)
+ labelFns: axes.makeLabelFns(ax, mainLinePosition + standoff * tickSigns[4])
});
});
seq.push(function() {
- labelLength += getLabelLevelSpan(ax, axId + 'tick2');
- ax._labelLength = labelLength;
+ ax._depth = tickSigns[4] * (getLabelLevelBbox('tick2')[ax.side] - mainLinePosition);
return drawDividers(gd, ax, {
vals: dividerVals,
layer: mainAxLayer,
- path: axes.makeTickPath(ax, mainLinePosition, sgn, labelLength),
+ path: axes.makeTickPath(ax, mainLinePosition, tickSigns[4], ax._depth),
transFn: transFn
});
});
- }
-
- function extendRange(range, newRange) {
- range[0] = Math.min(range[0], newRange[0]);
- range[1] = Math.max(range[1], newRange[1]);
- }
-
- function calcBoundingBox() {
- if(ax.showticklabels) {
- var gdBB = gd.getBoundingClientRect();
- var bBox = mainAxLayer.node().getBoundingClientRect();
-
- /*
- * the way we're going to use this, the positioning that matters
- * is relative to the origin of gd. This is important particularly
- * if gd is scrollable, and may have been scrolled between the time
- * we calculate this and the time we use it
- */
-
- ax._boundingBox = {
- width: bBox.width,
- height: bBox.height,
- left: bBox.left - gdBB.left,
- right: bBox.right - gdBB.left,
- top: bBox.top - gdBB.top,
- bottom: bBox.bottom - gdBB.top
- };
- } else {
- var gs = fullLayout._size;
- var pos;
-
- // set dummy bbox for ticklabel-less axes
-
- if(axLetter === 'x') {
- pos = ax.anchor === 'free' ?
- gs.t + gs.h * (1 - ax.position) :
- gs.t + gs.h * (1 - ax._anchorAxis.domain[{bottom: 0, top: 1}[ax.side]]);
-
- ax._boundingBox = {
- top: pos,
- bottom: pos,
- left: ax._offset,
- right: ax._offset + ax._length,
- width: ax._length,
- height: 0
- };
- } else {
- pos = ax.anchor === 'free' ?
- gs.l + gs.w * ax.position :
- gs.l + gs.w * ax._anchorAxis.domain[{left: 0, right: 1}[ax.side]];
-
- ax._boundingBox = {
- left: pos,
- right: pos,
- bottom: ax._offset + ax._length,
- top: ax._offset,
- height: ax._length,
- width: 0
- };
- }
- }
-
- /*
- * for spikelines: what's the full domain of positions in the
- * opposite direction that are associated with this axis?
- * This means any axes that we make a subplot with, plus the
- * position of the axis itself if it's free.
- */
- if(subplotsWithAx) {
- var fullRange = ax._counterSpan = [Infinity, -Infinity];
-
- for(var i = 0; i < subplotsWithAx.length; i++) {
- var plotinfo = fullLayout._plots[subplotsWithAx[i]];
- var counterAxis = plotinfo[(axLetter === 'x') ? 'yaxis' : 'xaxis'];
-
- extendRange(fullRange, [
- counterAxis._offset,
- counterAxis._offset + counterAxis._length
- ]);
- }
-
- if(ax.anchor === 'free') {
- extendRange(fullRange, (axLetter === 'x') ?
- [ax._boundingBox.bottom, ax._boundingBox.top] :
- [ax._boundingBox.right, ax._boundingBox.left]);
- }
- }
+ } else if(ax.title.hasOwnProperty('standoff')) {
+ seq.push(function() {
+ ax._depth = tickSigns[4] * (getLabelLevelBbox()[ax.side] - mainLinePosition);
+ });
}
var hasRangeSlider = Registry.getComponentMethod('rangeslider', 'isVisible')(ax);
- function doAutoMargins() {
+ seq.push(function() {
var s = ax.side.charAt(0);
+ var sMirror = OPPOSITE_SIDE[ax.side].charAt(0);
+ var pos = axes.getPxPosition(gd, ax);
+ var outsideTickLen = ax.ticks === 'outside' ? ax.ticklen : 0;
+ var llbbox;
+
var push;
+ var mirrorPush;
var rangeSliderPush;
- if(hasRangeSlider) {
- rangeSliderPush = Registry.getComponentMethod('rangeslider', 'autoMarginOpts')(gd, ax);
+ if(ax.automargin || hasRangeSlider) {
+ if(ax.type === 'multicategory') {
+ llbbox = getLabelLevelBbox('tick2');
+ } else {
+ llbbox = getLabelLevelBbox();
+ if(axLetter === 'x' && s === 'b') {
+ ax._depth = Math.max(llbbox.width > 0 ? llbbox.bottom - pos : 0, outsideTickLen);
+ }
+ }
}
- Plots.autoMargin(gd, rangeSliderAutoMarginID(ax), rangeSliderPush);
- if(ax.automargin && (!hasRangeSlider || s !== 'b')) {
+ if(ax.automargin) {
push = {x: 0, y: 0, r: 0, l: 0, t: 0, b: 0};
+ var domainIndices = [0, 1];
- var bbox = ax._boundingBox;
- var titleOffset = getTitleOffset(gd, ax);
- var anchorAxDomainIndex;
- var offset;
+ 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();
+ }
- switch(axLetter + s) {
- case 'xb':
- anchorAxDomainIndex = 0;
- offset = bbox.top - titleOffset;
- push[s] = bbox.height;
- break;
- case 'xt':
- anchorAxDomainIndex = 1;
- offset = titleOffset - bbox.bottom;
- push[s] = bbox.height;
- break;
- case 'yl':
- anchorAxDomainIndex = 0;
- offset = titleOffset - bbox.right;
- push[s] = bbox.width;
- break;
- case 'yr':
- anchorAxDomainIndex = 1;
- offset = bbox.left - titleOffset;
- push[s] = bbox.width;
- break;
+ 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[anchorAxDomainIndex];
-
- if(push[s] > 0) {
- push[s] += offset;
- }
+ ax._anchorAxis.domain[domainIndices[0]];
if(ax.title.text !== fullLayout._dfltTitle[axLetter]) {
- push[s] += ax.title.font.size;
+ push[s] += approxTitleDepth(ax) + (ax.title.standoff || 0);
}
- if(axLetter === 'x' && bbox.width > 0) {
- var rExtra = bbox.right - (ax._offset + ax._length);
- if(rExtra > 0) {
- push.x = 1;
- push.r = rExtra;
- }
- var lExtra = ax._offset - bbox.left;
- if(lExtra > 0) {
- push.x = 0;
- push.l = lExtra;
- }
- } else if(axLetter === 'y' && bbox.height > 0) {
- var bExtra = bbox.bottom - (ax._offset + ax._length);
- if(bExtra > 0) {
- push.y = 0;
- push.b = bExtra;
- }
- var tExtra = ax._offset - bbox.top;
- if(tExtra > 0) {
- push.y = 1;
- push.t = tExtra;
+ 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]];
}
}
}
- Plots.autoMargin(gd, axAutoMarginID(ax), push);
- }
+ if(hasRangeSlider) {
+ rangeSliderPush = Registry.getComponentMethod('rangeslider', 'autoMarginOpts')(gd, ax);
+ }
- seq.push(calcBoundingBox, doAutoMargins);
+ Plots.autoMargin(gd, axAutoMarginID(ax), push);
+ Plots.autoMargin(gd, axMirrorAutoMarginID(ax), mirrorPush);
+ Plots.autoMargin(gd, rangeSliderAutoMarginID(ax), rangeSliderPush);
+ });
if(!opts.skipTitle &&
- !(hasRangeSlider && ax._boundingBox && ax.side === 'bottom')
+ !(hasRangeSlider && ax.side === 'bottom')
) {
seq.push(function() { return drawTitle(gd, ax); });
}
@@ -51731,27 +51972,45 @@ function getDividerVals(ax, vals) {
return out;
}
-function getLabelLevelSpan(ax, cls) {
- var axLetter = ax._id.charAt(0);
- var angle = ax._tickAngles[cls] || 0;
- var rad = Lib.deg2rad(angle);
- var sinA = Math.sin(rad);
- var cosA = Math.cos(rad);
- var maxX = 0;
- var maxY = 0;
+function calcLabelLevelBbox(ax, cls) {
+ var top, bottom;
+ var left, right;
- // N.B. Drawing.bBox does not take into account rotate transforms
+ if(ax._selections[cls].size()) {
+ top = Infinity;
+ bottom = -Infinity;
+ left = Infinity;
+ right = -Infinity;
+ ax._selections[cls].each(function() {
+ var thisLabel = selectTickLabel(this);
+ // Use parent node
, to make Drawing.bBox
+ // retrieve a bbox computed with transform info
+ //
+ // To improve perf, it would be nice to use `thisLabel.node()`
+ // (like in fixLabelOverlaps) instead and use Axes.getPxPosition
+ // together with the makeLabelFns outputs and `tickangle`
+ // to compute one bbox per (tick value x tick style)
+ var 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;
+ }
- ax._selections[cls].each(function() {
- var thisLabel = selectTickLabel(this);
- var bb = Drawing.bBox(thisLabel.node());
- var w = bb.width;
- var h = bb.height;
- maxX = Math.max(maxX, cosA * w, sinA * h);
- maxY = Math.max(maxY, sinA * w, cosA * h);
- });
-
- return {x: maxY, y: maxX}[axLetter];
+ return {
+ top: top,
+ bottom: bottom,
+ left: left,
+ right: right,
+ height: bottom - top,
+ width: right - left
+ };
}
/**
@@ -51766,6 +52025,7 @@ function getLabelLevelSpan(ax, cls) {
* - [1]: sign for bottom/left ticks (i.e. positive SVG direction)
* - [2]: sign for ticks corresponding to 'ax.side'
* - [3]: sign for ticks mirroring 'ax.side'
+ * - [4]: sign of arrow starting at axis pointing towards margin
*/
axes.getTickSigns = function(ax) {
var axLetter = ax._id.charAt(0);
@@ -51776,6 +52036,10 @@ axes.getTickSigns = function(ax) {
if((ax.ticks !== 'inside') === (axLetter === 'x')) {
out = out.map(function(v) { return -v; });
}
+ // independent of `ticks`; do not flip this one
+ if(ax.side) {
+ out.push({l: -1, t: -1, r: 1, b: 1}[ax.side.charAt(0)]);
+ }
return out;
};
@@ -51804,7 +52068,7 @@ axes.makeTransFn = function(ax) {
* - {number} ticklen
* - {number} linewidth
* @param {number} shift along direction of ticklen
- * @param {1 or -1} sng tick sign
+ * @param {1 or -1} sgn tick sign
* @param {number (optional)} len tick length
* @return {string}
*/
@@ -52072,6 +52336,7 @@ axes.drawZeroLine = function(gd, ax, opts) {
* - {number} tickangle
* - {object (optional)} _selections
* - {object} (optional)} _tickAngles
+ * - {object} (optional)} _prevTickAngles
* @param {object} opts
* - {array of object} vals (calcTicks output-like)
* - {d3 selection} layer
@@ -52088,13 +52353,14 @@ axes.drawZeroLine = function(gd, ax, opts) {
axes.drawLabels = function(gd, ax, opts) {
opts = opts || {};
+ var fullLayout = gd._fullLayout;
var axId = ax._id;
var axLetter = axId.charAt(0);
var cls = opts.cls || axId + 'tick';
var vals = opts.vals;
var labelFns = opts.labelFns;
var tickAngle = opts.secondary ? 0 : ax.tickangle;
- var lastAngle = (ax._tickAngles || {})[cls];
+ var prevAngle = (ax._prevTickAngles || {})[cls];
var tickLabels = opts.layer.selectAll('g.' + cls)
.data(ax.showticklabels ? vals : [], tickDataFn);
@@ -52179,17 +52445,17 @@ axes.drawLabels = function(gd, ax, opts) {
// do this without waiting, using the last calculated angle to
// minimize flicker, then do it again when we know all labels are
// there, putting back the prescribed angle to check for overlaps.
- positionLabels(tickLabels, lastAngle || tickAngle);
+ positionLabels(tickLabels, (prevAngle + 1) ? prevAngle : tickAngle);
function allLabelsReady() {
return labelsReady.length && Promise.all(labelsReady);
}
+ var autoangle = null;
+
function fixLabelOverlaps() {
positionLabels(tickLabels, tickAngle);
- var autoangle = null;
-
// check for auto-angling if x labels overlap
// don't auto-angle at all for log axes with
// base and digit format
@@ -52256,19 +52522,36 @@ axes.drawLabels = function(gd, ax, opts) {
positionLabels(tickLabels, autoangle);
}
}
-
- if(ax._tickAngles) {
- ax._tickAngles[cls] = autoangle === null ?
- (isNumeric(tickAngle) ? tickAngle : 0) :
- autoangle;
- }
}
if(ax._selections) {
ax._selections[cls] = tickLabels;
}
- var done = Lib.syncOrAsync([allLabelsReady, fixLabelOverlaps]);
+ var seq = [allLabelsReady];
+
+ // N.B. during auto-margin redraws, if the axis fixed its label overlaps
+ // by rotating 90 degrees, do not attempt to re-fix its label overlaps
+ // as this can lead to infinite redraw loops!
+ if(ax.automargin && fullLayout._redrawFromAutoMarginCount && prevAngle === 90) {
+ autoangle = 90;
+ seq.push(function() {
+ positionLabels(tickLabels, prevAngle);
+ });
+ } else {
+ seq.push(fixLabelOverlaps);
+ }
+
+ // save current tick angle for future redraws
+ if(ax._tickAngles) {
+ seq.push(function() {
+ ax._tickAngles[cls] = autoangle === null ?
+ (isNumeric(tickAngle) ? tickAngle : 0) :
+ autoangle;
+ });
+ }
+
+ var done = Lib.syncOrAsync(seq);
if(done && done.then) gd._promises.push(done);
return done;
};
@@ -52308,14 +52591,28 @@ function drawDividers(gd, ax, opts) {
.attr('d', opts.path);
}
-function getTitleOffset(gd, ax) {
+/**
+ * Get axis position in px, that is the distance for the graph's
+ * top (left) edge for x (y) axes.
+ *
+ * @param {DOM element} gd
+ * @param {object} ax (full) axis object
+ * - {string} _id
+ * - {string} side
+ * if anchored:
+ * - {object} _anchorAxis
+ * Otherwise:
+ * - {number} position
+ * @return {number}
+ */
+axes.getPxPosition = function(gd, ax) {
var gs = gd._fullLayout._size;
var axLetter = ax._id.charAt(0);
var side = ax.side;
var anchorAxis;
if(ax.anchor !== 'free') {
- anchorAxis = axisIds.getFromId(gd, ax.anchor);
+ anchorAxis = ax._anchorAxis;
} else if(axLetter === 'x') {
anchorAxis = {
_offset: gs.t + (1 - (ax.position || 0)) * gs.h,
@@ -52333,8 +52630,48 @@ function getTitleOffset(gd, ax) {
} else if(side === 'bottom' || side === 'right') {
return anchorAxis._offset + anchorAxis._length;
}
+};
+
+/**
+ * Approximate axis title depth (w/o computing its bounding box)
+ *
+ * @param {object} ax (full) axis object
+ * - {string} title.text
+ * - {number} title.font.size
+ * - {number} title.standoff
+ * @return {number} (in px)
+ */
+function approxTitleDepth(ax) {
+ var fontSize = ax.title.font.size;
+ var extraLines = (ax.title.text.match(svgTextUtils.BR_TAG_ALL) || []).length;
+ if(ax.title.hasOwnProperty('standoff')) {
+ return extraLines ?
+ fontSize * (CAP_SHIFT + (extraLines * LINE_SPACING)) :
+ fontSize * CAP_SHIFT;
+ } else {
+ return extraLines ?
+ fontSize * (extraLines + 1) * LINE_SPACING :
+ fontSize;
+ }
}
+/**
+ * Draw axis title, compute default standoff if necessary
+ *
+ * @param {DOM element} gd
+ * @param {object} ax (full) axis object
+ * - {string} _id
+ * - {string} _name
+ * - {string} side
+ * - {number} title.font.size
+ * - {object} _selections
+ *
+ * - {number} _depth
+ * - {number} title.standoff
+ * OR
+ * - {number} linewidth
+ * - {boolean} showticklabels
+ */
function drawTitle(gd, ax) {
var fullLayout = gd._fullLayout;
var axId = ax._id;
@@ -52342,36 +52679,37 @@ function drawTitle(gd, ax) {
var fontSize = ax.title.font.size;
var titleStandoff;
- if(ax.type === 'multicategory') {
- titleStandoff = ax._labelLength;
+
+ if(ax.title.hasOwnProperty('standoff')) {
+ titleStandoff = ax._depth + ax.title.standoff + approxTitleDepth(ax);
} else {
- var offsetBase = 1.5;
- titleStandoff = 10 + fontSize * offsetBase + (ax.linewidth ? ax.linewidth - 1 : 0);
+ if(ax.type === 'multicategory') {
+ titleStandoff = ax._depth;
+ } else {
+ var offsetBase = 1.5;
+ titleStandoff = 10 + fontSize * offsetBase + (ax.linewidth ? ax.linewidth - 1 : 0);
+ }
+
+ if(axLetter === 'x') {
+ titleStandoff += ax.side === 'top' ?
+ fontSize * (ax.showticklabels ? 1 : 0) :
+ fontSize * (ax.showticklabels ? 1.5 : 0.5);
+ } else {
+ titleStandoff += ax.side === 'right' ?
+ fontSize * (ax.showticklabels ? 1 : 0.5) :
+ fontSize * (ax.showticklabels ? 0.5 : 0);
+ }
}
- var titleOffset = getTitleOffset(gd, ax);
-
+ var pos = axes.getPxPosition(gd, ax);
var transform, x, y;
if(axLetter === 'x') {
x = ax._offset + ax._length / 2;
-
- if(ax.side === 'top') {
- y = -titleStandoff - fontSize * (ax.showticklabels ? 1 : 0);
- } else {
- y = titleStandoff + fontSize * (ax.showticklabels ? 1.5 : 0.5);
- }
- y += titleOffset;
+ y = (ax.side === 'top') ? pos - titleStandoff : pos + titleStandoff;
} else {
y = ax._offset + ax._length / 2;
-
- if(ax.side === 'right') {
- x = titleStandoff + fontSize * (ax.showticklabels ? 1 : 0.5);
- } else {
- x = -titleStandoff - fontSize * (ax.showticklabels ? 0.5 : 0);
- }
- x += titleOffset;
-
+ x = (ax.side === 'right') ? pos + titleStandoff : pos - titleStandoff;
transform = {rotate: '-90', offset: 0};
}
@@ -52390,6 +52728,10 @@ function drawTitle(gd, ax) {
avoid.offsetLeft = translation.x;
avoid.offsetTop = translation.y;
}
+
+ if(ax.title.hasOwnProperty('standoff')) {
+ avoid.pad = 0;
+ }
}
return Titles.draw(gd, axId + 'title', {
@@ -52408,7 +52750,6 @@ axes.shouldShowZeroLine = function(gd, ax, counterAxis) {
(rng[0] * rng[1] <= 0) &&
ax.zeroline &&
(ax.type === 'linear' || ax.type === '-') &&
- ax._gridVals.length &&
(
clipEnds(ax, 0) ||
!anyCounterAxLineAtZero(gd, ax, counterAxis, rng) ||
@@ -52519,6 +52860,9 @@ axes.allowAutoMargin = function(gd) {
var ax = axList[i];
if(ax.automargin) {
Plots.allowAutoMargin(gd, axAutoMarginID(ax));
+ if(ax.mirror) {
+ Plots.allowAutoMargin(gd, axMirrorAutoMarginID(ax));
+ }
}
if(Registry.getComponentMethod('rangeslider', 'isVisible')(ax)) {
Plots.allowAutoMargin(gd, rangeSliderAutoMarginID(ax));
@@ -52527,6 +52871,7 @@ axes.allowAutoMargin = function(gd) {
};
function axAutoMarginID(ax) { return ax._id + '.automargin'; }
+function axMirrorAutoMarginID(ax) { return axAutoMarginID(ax) + '.mirror'; }
function rangeSliderAutoMarginID(ax) { return ax._id + '.rangeslider'; }
// swap all the presentation attributes of the axes showing these traces
@@ -52675,7 +53020,7 @@ function isAngular(ax) {
return ax._id === 'angularaxis';
}
-},{"../../components/color":51,"../../components/drawing":72,"../../components/titles":139,"../../constants/alignment":146,"../../constants/numerical":149,"../../lib":168,"../../lib/svg_text_utils":189,"../../plots/plots":244,"../../registry":256,"./autorange":211,"./axis_autotype":213,"./axis_ids":215,"./clean_ticks":217,"./layout_attributes":224,"./set_convert":230,"d3":16,"fast-isnumeric":18}],213:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../components/drawing":72,"../../components/titles":138,"../../constants/alignment":145,"../../constants/numerical":149,"../../lib":169,"../../lib/svg_text_utils":190,"../../plots/plots":245,"../../registry":258,"./autorange":212,"./axis_autotype":214,"./axis_ids":216,"./clean_ticks":218,"./layout_attributes":225,"./set_convert":231,"d3":16,"fast-isnumeric":18}],214:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -52770,7 +53115,7 @@ function multiCategory(a) {
return Lib.isArrayOrTypedArray(a[0]) && Lib.isArrayOrTypedArray(a[1]);
}
-},{"../../constants/numerical":149,"../../lib":168,"fast-isnumeric":18}],214:[function(_dereq_,module,exports){
+},{"../../constants/numerical":149,"../../lib":169,"fast-isnumeric":18}],215:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -52893,7 +53238,7 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce,
return containerOut;
};
-},{"../../lib":168,"../../registry":256,"./category_order_defaults":216,"./layout_attributes":224,"./line_grid_defaults":226,"./set_convert":230,"./tick_label_defaults":231,"./tick_mark_defaults":232,"./tick_value_defaults":233}],215:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../registry":258,"./category_order_defaults":217,"./layout_attributes":225,"./line_grid_defaults":227,"./set_convert":231,"./tick_label_defaults":232,"./tick_mark_defaults":233,"./tick_value_defaults":234}],216:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -53020,7 +53365,7 @@ exports.getAxisGroup = function getAxisGroup(fullLayout, axId) {
return axId;
};
-},{"../../registry":256,"./constants":218}],216:[function(_dereq_,module,exports){
+},{"../../registry":258,"./constants":219}],217:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -53114,7 +53459,7 @@ module.exports = function handleCategoryOrderDefaults(containerIn, containerOut,
}
};
-},{}],217:[function(_dereq_,module,exports){
+},{}],218:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -53202,7 +53547,7 @@ exports.tick0 = function(tick0, axType, calendar, dtick) {
return isNumeric(tick0) ? Number(tick0) : 0;
};
-},{"../../constants/numerical":149,"../../lib":168,"fast-isnumeric":18}],218:[function(_dereq_,module,exports){
+},{"../../constants/numerical":149,"../../lib":169,"fast-isnumeric":18}],219:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -53268,6 +53613,7 @@ module.exports = {
// Layers to keep trace types in the right order
// N.B. each 'unique' plot method must have its own layer
traceLayerClasses: [
+ 'imagelayer',
'heatmaplayer',
'contourcarpetlayer', 'contourlayer',
'funnellayer', 'waterfalllayer', 'barlayer',
@@ -53291,7 +53637,7 @@ module.exports = {
}
};
-},{"../../lib/regex":183}],219:[function(_dereq_,module,exports){
+},{"../../lib/regex":184}],220:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -53311,7 +53657,11 @@ 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, allAxisIds, layoutOut) {
+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;
@@ -53322,7 +53672,7 @@ exports.handleConstraintDefaults = function(containerIn, containerOut, coerce, a
// coerce the constraint mechanics even if this axis has no scaleanchor
// because it may be the anchor of another axis.
- var constrain = coerce('constrain');
+ var constrain = coerce('constrain', constrainDflt);
Lib.coerce(containerIn, containerOut, {
constraintoward: {
valType: 'enumerated',
@@ -53347,14 +53697,17 @@ exports.handleConstraintDefaults = function(containerIn, containerOut, coerce, a
// 'matches' wins over 'scaleanchor' (for now)
var scaleanchor, scaleOpts;
- if(!matches && containerIn.scaleanchor && !(containerOut.fixedrange && constrain !== 'domain')) {
+ 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');
+ }, 'scaleanchor', scaleanchorDflt);
}
if(matches) {
@@ -53670,7 +54023,7 @@ function updateDomain(ax, factor) {
ax.setScale();
}
-},{"../../constants/alignment":146,"../../constants/numerical":149,"../../lib":168,"./autorange":211,"./axis_ids":215,"./scale_zoom":228}],220:[function(_dereq_,module,exports){
+},{"../../constants/alignment":145,"../../constants/numerical":149,"../../lib":169,"./autorange":212,"./axis_ids":216,"./scale_zoom":229}],221:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -53724,9 +54077,9 @@ var SHOWZOOMOUTTIP = true;
// ew - same for horizontal axis
function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) {
// mouseDown stores ms of first mousedown event in the last
- // DBLCLICKDELAY ms on the drag bars
+ // `gd._context.doubleClickDelay` ms on the drag bars
// numClicks stores how many mousedowns have been seen
- // within DBLCLICKDELAY so we can check for click or doubleclick events
+ // within `gd._context.doubleClickDelay` so we can check for click or doubleclick events
// dragged stores whether a drag has occurred, so we don't have to
// redraw unnecessarily, ie if no move bigger than MINDRAG or MINZOOM px
var zoomlayer = gd._fullLayout._zoomlayer;
@@ -54102,14 +54455,7 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) {
}
function zoomDone() {
- // more strict than dragged, which allows you to come back to where you started
- // and still count as dragged
- if(Math.min(box.h, box.w) < MINDRAG * 2) {
- return removeZoombox(gd);
- }
-
computeZoomUpdates();
-
removeZoombox(gd);
dragTail();
showDoubleClickNotifier(gd);
@@ -54917,7 +55263,7 @@ module.exports = {
attachWheelEventHandler: attachWheelEventHandler
};
-},{"../../components/color":51,"../../components/dragelement":69,"../../components/drawing":72,"../../components/fx":90,"../../constants/alignment":146,"../../lib":168,"../../lib/clear_gl_canvases":157,"../../lib/setcursor":187,"../../lib/svg_text_utils":189,"../../plot_api/subroutines":203,"../../registry":256,"../plots":244,"./axes":212,"./axis_ids":215,"./constants":218,"./scale_zoom":228,"./select":229,"d3":16,"has-passive-events":21,"tinycolor2":34}],221:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../components/dragelement":69,"../../components/drawing":72,"../../components/fx":89,"../../constants/alignment":145,"../../lib":169,"../../lib/clear_gl_canvases":158,"../../lib/setcursor":188,"../../lib/svg_text_utils":190,"../../plot_api/subroutines":204,"../../registry":258,"../plots":245,"./axes":213,"./axis_ids":216,"./constants":219,"./scale_zoom":229,"./select":230,"d3":16,"has-passive-events":21,"tinycolor2":34}],222:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -54979,7 +55325,7 @@ exports.initInteractions = function initInteractions(gd) {
// This is on `gd._fullLayout`, *not* fullLayout because the reference
// changes by the time this is called again.
gd._fullLayout._rehover = function() {
- if(gd._fullLayout._hoversubplot === subplot) {
+ if((gd._fullLayout._hoversubplot === subplot) && gd._fullLayout._plots[subplot]) {
Fx.hover(gd, evt, subplot);
}
};
@@ -55085,7 +55431,7 @@ exports.updateFx = function(gd) {
setCursor(fullLayout._draggers, cursor);
};
-},{"../../components/dragelement":69,"../../components/fx":90,"../../lib/setcursor":187,"./constants":218,"./dragbox":220,"d3":16}],222:[function(_dereq_,module,exports){
+},{"../../components/dragelement":69,"../../components/fx":89,"../../lib/setcursor":188,"./constants":219,"./dragbox":221,"d3":16}],223:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -55160,7 +55506,7 @@ module.exports = function makeIncludeComponents(containerArrayName) {
};
};
-},{"../../lib":168,"../../registry":256}],223:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../registry":258}],224:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -55402,7 +55748,8 @@ function plotOne(gd, plotinfo, cdSubplot, transitionOpts, makeOnCompleteCallback
layers.enter().append('g')
.attr('class', function(d) { return d.className; })
- .classed('mlayer', true);
+ .classed('mlayer', true)
+ .classed('rangeplot', plotinfo.isRangePlot);
layers.exit().remove();
@@ -55776,7 +56123,7 @@ exports.toSVG = function(gd) {
exports.updateFx = _dereq_('./graph_interact').updateFx;
-},{"../../components/drawing":72,"../../constants/xmlns_namespaces":150,"../../lib":168,"../../registry":256,"../get_data":240,"../plots":244,"./attributes":210,"./axis_ids":215,"./constants":218,"./graph_interact":221,"./layout_attributes":224,"./layout_defaults":225,"./transition_axes":234,"d3":16}],224:[function(_dereq_,module,exports){
+},{"../../components/drawing":72,"../../constants/xmlns_namespaces":150,"../../lib":169,"../../registry":258,"../get_data":241,"../plots":245,"./attributes":211,"./axis_ids":216,"./constants":219,"./graph_interact":222,"./layout_attributes":225,"./layout_defaults":226,"./transition_axes":235,"d3":16}],225:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -55793,8 +56140,10 @@ var dash = _dereq_('../../components/drawing/attributes').dash;
var extendFlat = _dereq_('../../lib/extend').extendFlat;
var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray;
-var constants = _dereq_('./constants');
+var FORMAT_LINK = _dereq_('../../constants/docs').FORMAT_LINK;
+var DATE_FORMAT_LINK = _dereq_('../../constants/docs').DATE_FORMAT_LINK;
+var constants = _dereq_('./constants');
module.exports = {
visible: {
@@ -55821,6 +56170,13 @@ module.exports = {
editType: 'ticks',
}),
+ standoff: {
+ valType: 'number',
+
+ min: 0,
+ editType: 'ticks',
+
+ },
editType: 'ticks'
},
type: {
@@ -56368,7 +56724,7 @@ module.exports = {
}
};
-},{"../../components/color/attributes":50,"../../components/drawing/attributes":71,"../../lib/extend":162,"../../plot_api/plot_template":202,"../font_attributes":238,"./constants":218}],225:[function(_dereq_,module,exports){
+},{"../../components/color/attributes":50,"../../components/drawing/attributes":71,"../../constants/docs":146,"../../lib/extend":164,"../../plot_api/plot_template":203,"../font_attributes":239,"./constants":219}],226:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -56410,8 +56766,9 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
var yaMayHide = {};
var xaMustDisplay = {};
var yaMustDisplay = {};
- var yaMustForward = {};
- var yaMayBackward = {};
+ var yaMustNotReverse = {};
+ var yaMayReverse = {};
+ var axHasImage = {};
var outerTicks = {};
var noGrids = {};
var i, j;
@@ -56445,14 +56802,17 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
if(trace.type === 'funnel') {
if(trace.orientation === 'h') {
if(xaName) xaMayHide[xaName] = true;
- if(yaName) yaMayBackward[yaName] = true;
+ if(yaName) yaMayReverse[yaName] = true;
} else {
if(yaName) yaMayHide[yaName] = true;
}
+ } else if(trace.type === 'image') {
+ if(yaName) axHasImage[yaName] = true;
+ if(xaName) axHasImage[xaName] = true;
} else {
if(yaName) {
yaMustDisplay[yaName] = true;
- yaMustForward[yaName] = true;
+ yaMustNotReverse[yaName] = true;
}
if(!traceIs(trace, 'carpet') || (trace.type === 'carpet' && !trace._cheater)) {
@@ -56563,7 +56923,11 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
(axLetter === 'y' && !yaMustDisplay[axName] && yaMayHide[axName]);
var reverseDflt =
- (axLetter === 'y' && !yaMustForward[axName] && yaMayBackward[axName]);
+ (axLetter === 'y' &&
+ (
+ (!yaMustNotReverse[axName] && yaMayReverse[axName]) ||
+ axHasImage[axName]
+ ));
var defaultOptions = {
letter: axLetter,
@@ -56606,6 +56970,8 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
grid: layoutOut.grid
});
+ coerce('title.standoff');
+
axLayoutOut._input = axLayoutIn;
}
@@ -56663,7 +57029,22 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
axLayoutIn = layoutIn[axName];
axLayoutOut = layoutOut[axName];
- handleConstraintDefaults(axLayoutIn, axLayoutOut, coerce, allAxisIds, layoutOut);
+ var scaleanchorDflt;
+ if(axLetter === 'y' && !axLayoutIn.hasOwnProperty('scaleanchor') && axHasImage[axName]) {
+ scaleanchorDflt = axLayoutOut.anchor;
+ } else {scaleanchorDflt = undefined;}
+
+ var constrainDflt;
+ if(!axLayoutIn.hasOwnProperty('constrain') && axHasImage[axName]) {
+ constrainDflt = 'domain';
+ } else {constrainDflt = undefined;}
+
+ handleConstraintDefaults(axLayoutIn, axLayoutOut, coerce, {
+ allAxisIds: allAxisIds,
+ layoutOut: layoutOut,
+ scaleanchorDflt: scaleanchorDflt,
+ constrainDflt: constrainDflt
+ });
}
for(i = 0; i < matchGroups.length; i++) {
@@ -56723,7 +57104,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
}
};
-},{"../../components/color":51,"../../lib":168,"../../plot_api/plot_template":202,"../../registry":256,"../layout_attributes":242,"./axis_defaults":214,"./axis_ids":215,"./constraints":219,"./layout_attributes":224,"./position_defaults":227,"./type_defaults":235}],226:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../lib":169,"../../plot_api/plot_template":203,"../../registry":258,"../layout_attributes":243,"./axis_defaults":215,"./axis_ids":216,"./constraints":220,"./layout_attributes":225,"./position_defaults":228,"./type_defaults":236}],227:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -56788,7 +57169,7 @@ module.exports = function handleLineGridDefaults(containerIn, containerOut, coer
}
};
-},{"../../components/color/attributes":50,"../../lib":168,"tinycolor2":34}],227:[function(_dereq_,module,exports){
+},{"../../components/color/attributes":50,"../../lib":169,"tinycolor2":34}],228:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -56876,7 +57257,7 @@ module.exports = function handlePositionDefaults(containerIn, containerOut, coer
return containerOut;
};
-},{"../../lib":168,"fast-isnumeric":18}],228:[function(_dereq_,module,exports){
+},{"../../lib":169,"fast-isnumeric":18}],229:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -56904,7 +57285,7 @@ module.exports = function scaleZoom(ax, factor, centerFraction) {
];
};
-},{"../../constants/alignment":146}],229:[function(_dereq_,module,exports){
+},{"../../constants/alignment":145}],230:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -57641,7 +58022,10 @@ function updateSelectedState(gd, searchTraces, eventData) {
var _module = searchInfo._module;
var fn = _module.styleOnSelect || _module.style;
- if(fn) fn(gd, cd);
+ if(fn) {
+ fn(gd, cd, cd[0].node3);
+ if(cd[0].nodeRangePlot3) fn(gd, cd, cd[0].nodeRangePlot3);
+ }
}
if(hasRegl) {
@@ -57706,7 +58090,7 @@ module.exports = {
selectOnClick: selectOnClick
};
-},{"../../components/color":51,"../../components/fx":90,"../../components/fx/helpers":86,"../../lib":168,"../../lib/clear_gl_canvases":157,"../../lib/polygon":180,"../../lib/throttle":190,"../../plot_api/subroutines":203,"../../registry":256,"./axis_ids":215,"./constants":218,"polybooljs":25}],230:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../components/fx":89,"../../components/fx/helpers":86,"../../lib":169,"../../lib/clear_gl_canvases":158,"../../lib/polygon":181,"../../lib/throttle":191,"../../plot_api/subroutines":204,"../../registry":258,"./axis_ids":216,"./constants":219,"polybooljs":25}],231:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -58107,6 +58491,10 @@ module.exports = function setConvert(ax, fullLayout) {
// make sure we don't later mutate the defaults
dflt = dflt.slice();
+ if(ax.rangemode === 'tozero' || ax.rangemode === 'nonnegative') {
+ dflt[0] = 0;
+ }
+
if(!range || range.length !== 2) {
Lib.nestedProperty(ax, rangeAttr).set(dflt);
return;
@@ -58372,7 +58760,7 @@ module.exports = function setConvert(ax, fullLayout) {
delete ax._forceTick0;
};
-},{"../../constants/numerical":149,"../../lib":168,"./axis_ids":215,"./constants":218,"d3":16,"fast-isnumeric":18}],231:[function(_dereq_,module,exports){
+},{"../../constants/numerical":149,"../../lib":169,"./axis_ids":216,"./constants":219,"d3":16,"fast-isnumeric":18}],232:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -58491,7 +58879,7 @@ function tickformatstopDefaults(valueIn, valueOut) {
}
}
-},{"../../lib":168,"../array_container_defaults":208,"./layout_attributes":224}],232:[function(_dereq_,module,exports){
+},{"../../lib":169,"../array_container_defaults":209,"./layout_attributes":225}],233:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -58524,7 +58912,7 @@ module.exports = function handleTickDefaults(containerIn, containerOut, coerce,
}
};
-},{"../../lib":168,"./layout_attributes":224}],233:[function(_dereq_,module,exports){
+},{"../../lib":169,"./layout_attributes":225}],234:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -58566,7 +58954,7 @@ module.exports = function handleTickValueDefaults(containerIn, containerOut, coe
}
};
-},{"./clean_ticks":217}],234:[function(_dereq_,module,exports){
+},{"./clean_ticks":218}],235:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -58580,6 +58968,7 @@ module.exports = function handleTickValueDefaults(containerIn, containerOut, coe
var d3 = _dereq_('d3');
var Registry = _dereq_('../../registry');
+var Lib = _dereq_('../../lib');
var Drawing = _dereq_('../../components/drawing');
var Axes = _dereq_('./axes');
@@ -58638,37 +59027,35 @@ module.exports = function transitionAxes(gd, edits, transitionOpts, makeOnComple
var plotinfo = edit.plotinfo;
var xa = plotinfo.xaxis;
var ya = plotinfo.yaxis;
-
- var xr0 = edit.xr0;
- var xr1 = edit.xr1;
var xlen = xa._length;
- var yr0 = edit.yr0;
- var yr1 = edit.yr1;
var ylen = ya._length;
-
- var editX = !!xr1;
- var editY = !!yr1;
+ 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] = xr0[0] * (1 - progress) + progress * xr1[0];
- xa.range[1] = xr0[1] * (1 - progress) + progress * xr1[1];
+ 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] = yr0[0] * (1 - progress) + progress * yr1[0];
- ya.range[1] = yr0[1] * (1 - progress) + progress * yr1[1];
+ 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;
@@ -58713,8 +59100,10 @@ module.exports = function transitionAxes(gd, edits, transitionOpts, makeOnComple
for(var i = 0; i < edits.length; i++) {
var edit = edits[i];
- if(edit.xr1) aobj[edit.plotinfo.xaxis._name + '.range'] = edit.xr1.slice();
- if(edit.yr1) aobj[edit.plotinfo.yaxis._name + '.range'] = edit.yr1.slice();
+ var xa = edit.plotinfo.xaxis;
+ var ya = edit.plotinfo.yaxis;
+ if(edit.xr1) aobj[xa._name + '.range'] = edit.xr1.slice();
+ if(edit.yr1) aobj[ya._name + '.range'] = edit.yr1.slice();
}
// Signal that this transition has completed:
@@ -58732,8 +59121,10 @@ module.exports = function transitionAxes(gd, edits, transitionOpts, makeOnComple
for(var i = 0; i < edits.length; i++) {
var edit = edits[i];
- if(edit.xr0) aobj[edit.plotinfo.xaxis._name + '.range'] = edit.xr0.slice();
- if(edit.yr0) aobj[edit.plotinfo.yaxis._name + '.range'] = edit.yr0.slice();
+ var xa = edit.plotinfo.xaxis;
+ var ya = edit.plotinfo.yaxis;
+ if(edit.xr0) aobj[xa._name + '.range'] = edit.xr0.slice();
+ if(edit.yr0) aobj[ya._name + '.range'] = edit.yr0.slice();
}
return Registry.call('relayout', gd, aobj).then(function() {
@@ -58776,7 +59167,7 @@ module.exports = function transitionAxes(gd, edits, transitionOpts, makeOnComple
return Promise.resolve();
};
-},{"../../components/drawing":72,"../../registry":256,"./axes":212,"d3":16}],235:[function(_dereq_,module,exports){
+},{"../../components/drawing":72,"../../lib":169,"../../registry":258,"./axes":213,"d3":16}],236:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -58905,7 +59296,7 @@ function isBoxWithoutPositionCoords(trace, axLetter) {
);
}
-},{"../../registry":256,"./axis_autotype":213}],236:[function(_dereq_,module,exports){
+},{"../../registry":258,"./axis_autotype":214}],237:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -59268,9 +59659,13 @@ function computeDataBindings(gd, args) {
traces = null;
}
- crawl(aobj, function(path, attrName, attr) {
+ crawl(aobj, function(path, attrName, _attr) {
var thisTraces;
- if(Array.isArray(attr)) {
+ var attr;
+
+ if(Array.isArray(_attr)) {
+ attr = _attr.slice();
+
var nAttr = Math.min(attr.length, gd.data.length);
if(traces) {
nAttr = Math.min(nAttr, traces.length);
@@ -59280,7 +59675,8 @@ function computeDataBindings(gd, args) {
thisTraces[j] = traces ? traces[j] : j;
}
} else {
- thisTraces = traces ? traces.slice(0) : null;
+ attr = _attr;
+ thisTraces = traces ? traces.slice() : null;
}
// Convert [7] to just 7 when traces is null:
@@ -59327,7 +59723,7 @@ function crawl(attrs, callback, path, depth) {
});
}
-},{"../lib":168,"../registry":256}],237:[function(_dereq_,module,exports){
+},{"../lib":169,"../registry":258}],238:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -59431,11 +59827,15 @@ exports.defaults = function(containerOut, layout, coerce, dfltDomains) {
}
}
- coerce('domain.x', dfltX);
- coerce('domain.y', dfltY);
+ var x = coerce('domain.x', dfltX);
+ var y = coerce('domain.y', dfltY);
+
+ // don't accept bad input data
+ if(!(x[0] < x[1])) containerOut.domain.x = dfltX.slice();
+ if(!(y[0] < y[1])) containerOut.domain.y = dfltY.slice();
};
-},{"../lib/extend":162}],238:[function(_dereq_,module,exports){
+},{"../lib/extend":164}],239:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -59500,7 +59900,7 @@ module.exports = function(opts) {
return attrs;
};
-},{}],239:[function(_dereq_,module,exports){
+},{}],240:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -59546,7 +59946,7 @@ module.exports = {
}
};
-},{}],240:[function(_dereq_,module,exports){
+},{}],241:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -59675,7 +60075,7 @@ exports.getSubplotData = function getSubplotData(data, type, subplotId) {
return subplotData;
};
-},{"../registry":256,"./cartesian/constants":218}],241:[function(_dereq_,module,exports){
+},{"../registry":258,"./cartesian/constants":219}],242:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -59709,7 +60109,7 @@ function project(camera, v) {
module.exports = project;
-},{}],242:[function(_dereq_,module,exports){
+},{}],243:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -59872,7 +60272,8 @@ module.exports = {
valType: 'boolean',
dflt: true,
- editType: 'plot'
+ editType: 'plot',
+
},
editType: 'plot'
},
@@ -59998,7 +60399,6 @@ module.exports = {
editType: 'none'
}),
-
_deprecated: {
title: {
valType: 'string',
@@ -60013,7 +60413,7 @@ module.exports = {
}
};
-},{"../components/color/attributes":50,"../lib/extend":162,"./animation_attributes":207,"./font_attributes":238,"./pad_attributes":243}],243:[function(_dereq_,module,exports){
+},{"../components/color/attributes":50,"../lib/extend":164,"./animation_attributes":208,"./font_attributes":239,"./pad_attributes":244}],244:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -60068,7 +60468,7 @@ module.exports = function(opts) {
};
};
-},{}],244:[function(_dereq_,module,exports){
+},{}],245:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -60094,6 +60494,8 @@ var axisIDs = _dereq_('./cartesian/axis_ids');
var animationAttrs = _dereq_('./animation_attributes');
var frameAttrs = _dereq_('./frame_attributes');
+var getModuleCalcData = _dereq_('../plots/get_data').getModuleCalcData;
+
var relinkPrivateKeys = Lib.relinkPrivateKeys;
var _ = Lib._;
@@ -60145,21 +60547,19 @@ plots.redrawText = function(gd) {
plots.resize = function(gd) {
gd = Lib.getGraphDiv(gd);
- return new Promise(function(resolve, reject) {
- function isHidden(gd) {
- var display = window.getComputedStyle(gd).display;
- return !display || display === 'none';
- }
-
- if(!gd || isHidden(gd)) {
+ var resolveLastResize;
+ var p = new Promise(function(resolve, reject) {
+ if(!gd || Lib.isHidden(gd)) {
reject(new Error('Resize must be passed a displayed plot div element.'));
}
if(gd._redrawTimer) clearTimeout(gd._redrawTimer);
+ if(gd._resolveResize) resolveLastResize = gd._resolveResize;
+ gd._resolveResize = resolve;
gd._redrawTimer = setTimeout(function() {
// return if there is nothing to resize or is hidden
- if(!gd.layout || (gd.layout.width && gd.layout.height) || isHidden(gd)) {
+ if(!gd.layout || (gd.layout.width && gd.layout.height) || Lib.isHidden(gd)) {
resolve(gd);
return;
}
@@ -60175,10 +60575,17 @@ plots.resize = function(gd) {
Registry.call('relayout', gd, {autosize: true}).then(function() {
gd.changed = oldchanged;
- resolve(gd);
+ // Only resolve if a new call hasn't been made!
+ if(gd._resolveResize === resolve) {
+ delete gd._resolveResize;
+ resolve(gd);
+ }
});
}, 100);
});
+
+ if(resolveLastResize) resolveLastResize(p);
+ return p;
};
@@ -60996,6 +61403,26 @@ plots.linkSubplots = function(newFullData, newFullLayout, oldFullData, oldFullLa
ax._counterAxes.sort(axisIDs.idSort);
ax._subplotsWith.sort(Lib.subplotSort);
ax._mainSubplot = findMainSubplot(ax, newFullLayout);
+
+ // find "full" domain span of counter axes,
+ // this loop can be costly, so only compute it when required
+ if(ax._counterAxes.length && (
+ (ax.spikemode && ax.spikemode.indexOf('across') !== -1) ||
+ (ax.automargin && ax.mirror && ax.anchor !== 'free') ||
+ Registry.getComponentMethod('rangeslider', 'isVisible')(ax)
+ )) {
+ var min = 1;
+ var max = 0;
+ for(j = 0; j < ax._counterAxes.length; j++) {
+ var ax2 = axisIDs.getFromId(mockGd, ax._counterAxes[j]);
+ min = Math.min(min, ax2.domain[0]);
+ max = Math.max(max, ax2.domain[1]);
+ }
+ if(min < max) {
+ ax._counterDomainMin = min;
+ ax._counterDomainMax = max;
+ }
+ }
}
};
@@ -61721,7 +62148,6 @@ plots.purge = function(gd) {
fullLayout._glcontainer.remove();
fullLayout._glcanvas = null;
}
- if(fullLayout._geocontainer !== undefined) fullLayout._geocontainer.remove();
// remove modebar
if(fullLayout._modeBar) fullLayout._modeBar.destroy();
@@ -61896,8 +62322,14 @@ plots.autoMargin = function(gd, id, o) {
// if the item is too big, just give it enough automargin to
// make sure you can still grab it and bring it back
- if(o.l + o.r > fullLayout.width * 0.5) o.l = o.r = 0;
- if(o.b + o.t > fullLayout.height * 0.5) o.b = o.t = 0;
+ if(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;
@@ -61914,7 +62346,7 @@ plots.autoMargin = function(gd, id, o) {
}
if(!fullLayout._replotting) {
- plots.doAutoMargin(gd);
+ return plots.doAutoMargin(gd);
}
}
};
@@ -62011,7 +62443,19 @@ plots.doAutoMargin = function(gd) {
} else {
fullLayout._redrawFromAutoMarginCount = 1;
}
- return Registry.call('plot', gd);
+
+ // Always allow at least one redraw and give each margin-push
+ // call 3 loops to converge. Of course, for most cases this way too many,
+ // but let's keep things on the safe side until we fix our
+ // auto-margin pipeline problems:
+ // https://github.com/plotly/plotly.js/issues/2704
+ var maxNumberOfRedraws = 3 * (1 + Object.keys(pushMarginIds).length);
+
+ if(fullLayout._redrawFromAutoMarginCount < maxNumberOfRedraws) {
+ return Registry.call('plot', gd);
+ } else {
+ Lib.warn('Too many auto-margin redraws.');
+ }
}
};
@@ -62483,27 +62927,30 @@ plots.transition = function(gd, data, layout, traces, frameOpts, transitionOpts)
var xr0 = xa.range.slice();
var yr0 = ya.range.slice();
- var xr1;
+ var xr1 = null;
+ var yr1 = null;
+ var editX = null;
+ var editY = null;
+
if(Array.isArray(newLayout[xa._name + '.range'])) {
xr1 = newLayout[xa._name + '.range'].slice();
} else if(Array.isArray((newLayout[xa._name] || {}).range)) {
xr1 = newLayout[xa._name].range.slice();
}
-
- var yr1;
if(Array.isArray(newLayout[ya._name + '.range'])) {
yr1 = newLayout[ya._name + '.range'].slice();
} else if(Array.isArray((newLayout[ya._name] || {}).range)) {
yr1 = newLayout[ya._name].range.slice();
}
- var editX;
- if(xr0 && xr1 && (xr0[0] !== xr1[0] || xr0[1] !== xr1[1])) {
+ if(xr0 && xr1 &&
+ (xa.r2l(xr0[0]) !== xa.r2l(xr1[0]) || xa.r2l(xr0[1]) !== xa.r2l(xr1[1]))
+ ) {
editX = {xr0: xr0, xr1: xr1};
}
-
- var editY;
- if(yr0 && yr1 && (yr0[0] !== yr1[0] || yr0[1] !== yr1[1])) {
+ if(yr0 && yr1 &&
+ (ya.r2l(yr0[0]) !== ya.r2l(yr1[0]) || ya.r2l(yr0[1]) !== ya.r2l(yr1[1]))
+ ) {
editY = {yr0: yr0, yr1: yr1};
}
@@ -62594,13 +63041,13 @@ plots.transitionFromReact = function(gd, restyleFlags, relayoutFlags, oldFullLay
xa.setScale();
ya.setScale();
- var editX;
- if(xr0[0] !== xr1[0] || xr0[1] !== xr1[1]) {
+ var editX = null;
+ var editY = null;
+
+ if(xa.r2l(xr0[0]) !== xa.r2l(xr1[0]) || xa.r2l(xr0[1]) !== xa.r2l(xr1[1])) {
editX = {xr0: xr0, xr1: xr1};
}
-
- var editY;
- if(yr0[0] !== yr1[0] || yr0[1] !== yr1[1]) {
+ if(ya.r2l(yr0[0]) !== ya.r2l(yr1[0]) || ya.r2l(yr0[1]) !== ya.r2l(yr1[1])) {
editY = {yr0: yr0, yr1: yr1};
}
@@ -62645,14 +63092,14 @@ plots.transitionFromReact = function(gd, restyleFlags, relayoutFlags, oldFullLay
axisTransitionOpts = Lib.extendFlat({}, transitionOpts, {duration: 0});
transitionedTraces = allTraceIndices;
traceTransitionOpts = transitionOpts;
- transitionTraces();
setTimeout(transitionAxes, transitionOpts.duration);
+ transitionTraces();
} else {
axisTransitionOpts = transitionOpts;
transitionedTraces = null;
traceTransitionOpts = Lib.extendFlat({}, transitionOpts, {duration: 0});
+ setTimeout(transitionTraces, axisTransitionOpts.duration);
transitionAxes();
- transitionTraces();
}
} else if(axEdits.length) {
axisTransitionOpts = transitionOpts;
@@ -62813,7 +63260,7 @@ plots.doCalcdata = function(gd, traces) {
// XXX: Is this correct? Needs a closer look so that *some* traces can be recomputed without
// *all* needing doCalcdata:
var calcdata = new Array(fullData.length);
- var oldCalcdata = (gd.calcdata || []).slice(0);
+ var oldCalcdata = (gd.calcdata || []).slice();
gd.calcdata = calcdata;
// extra helper variables
@@ -62829,9 +63276,10 @@ plots.doCalcdata = function(gd, traces) {
gd._hmpixcount = 0;
gd._hmlumcount = 0;
- // for sharing colors across pies / sunbursts / funnelarea (and for legend)
+ // for sharing colors across pies / sunbursts / treemap / funnelarea (and for legend)
fullLayout._piecolormap = {};
fullLayout._sunburstcolormap = {};
+ fullLayout._treemapcolormap = {};
fullLayout._funnelareacolormap = {};
// If traces were specified and this trace was not included,
@@ -62861,6 +63309,15 @@ plots.doCalcdata = function(gd, traces) {
);
}
+ // clear relinked cmin/cmax values in shared axes to start aggregation from scratch
+ for(var k in fullLayout._colorAxes) {
+ var cOpts = fullLayout[k];
+ if(cOpts.cauto !== false) {
+ delete cOpts.cmin;
+ delete cOpts.cmax;
+ }
+ }
+
var hasCalcTransform = false;
function transformCalci(i) {
@@ -62958,6 +63415,9 @@ plots.doCalcdata = function(gd, traces) {
// Sort axis categories per value if specified
var sorted = sortAxisCategoriesByValue(axList, gd);
if(sorted.length) {
+ // how many box/violins plots do we have (in case they're grouped)
+ fullLayout._numBoxes = 0;
+ fullLayout._numViolins = 0;
// If a sort operation was performed, run calc() again
for(i = 0; i < sorted.length; i++) calci(sorted[i], true);
for(i = 0; i < sorted.length; i++) calci(sorted[i], false);
@@ -63259,7 +63719,22 @@ plots.generalUpdatePerTraceModule = function(gd, subplot, subplotCalcData, subpl
subplot.traceHash = traceHash;
};
-},{"../components/color":51,"../constants/numerical":149,"../lib":168,"../plot_api/plot_schema":201,"../plot_api/plot_template":202,"../registry":256,"./animation_attributes":207,"./attributes":209,"./cartesian/axis_ids":215,"./command":236,"./font_attributes":238,"./frame_attributes":239,"./layout_attributes":242,"d3":16,"fast-isnumeric":18}],245:[function(_dereq_,module,exports){
+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":51,"../constants/numerical":149,"../lib":169,"../plot_api/plot_schema":202,"../plot_api/plot_template":203,"../plots/get_data":241,"../registry":258,"./animation_attributes":208,"./attributes":210,"./cartesian/axis_ids":216,"./command":237,"./font_attributes":239,"./frame_attributes":240,"./layout_attributes":243,"d3":16,"fast-isnumeric":18}],246:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -63303,7 +63778,7 @@ module.exports = {
}
};
-},{"../../../lib/extend":162,"../../../traces/scatter/attributes":365}],246:[function(_dereq_,module,exports){
+},{"../../../lib/extend":164,"../../../traces/scatter/attributes":377}],247:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -63425,7 +63900,7 @@ module.exports = overrideAll({
}
}, 'plot', 'nested');
-},{"../../../lib/extend":162,"../../../plot_api/edit_types":195,"../../cartesian/layout_attributes":224}],247:[function(_dereq_,module,exports){
+},{"../../../lib/extend":164,"../../../plot_api/edit_types":196,"../../cartesian/layout_attributes":225}],248:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -63440,7 +63915,7 @@ var Polar = module.exports = _dereq_('./micropolar');
Polar.manager = _dereq_('./micropolar_manager');
-},{"./micropolar":248,"./micropolar_manager":249}],248:[function(_dereq_,module,exports){
+},{"./micropolar":249,"./micropolar_manager":250}],249:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -64860,7 +65335,7 @@ var µ = module.exports = { version: '0.2.2' };
return exports;
};
-},{"../../../constants/alignment":146,"../../../lib":168,"d3":16}],249:[function(_dereq_,module,exports){
+},{"../../../constants/alignment":145,"../../../lib":169,"d3":16}],250:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -64946,7 +65421,7 @@ manager.fillLayout = function(_gd) {
_gd._fullLayout = extendDeepAll(dflts, _gd.layout);
};
-},{"../../../components/color":51,"../../../lib":168,"./micropolar":248,"./undo_manager":250,"d3":16}],250:[function(_dereq_,module,exports){
+},{"../../../components/color":51,"../../../lib":169,"./micropolar":249,"./undo_manager":251,"d3":16}],251:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -65012,7 +65487,7 @@ module.exports = function UndoManager() {
};
};
-},{}],251:[function(_dereq_,module,exports){
+},{}],252:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -65097,7 +65572,90 @@ module.exports = function handleSubplotDefaults(layoutIn, layoutOut, fullData, o
}
};
-},{"../lib":168,"../plot_api/plot_template":202,"./domain":237}],252:[function(_dereq_,module,exports){
+},{"../lib":169,"../plot_api/plot_template":203,"./domain":238}],253:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+var FORMAT_LINK = _dereq_('../constants/docs').FORMAT_LINK;
+var DATE_FORMAT_LINK = _dereq_('../constants/docs').DATE_FORMAT_LINK;
+
+var templateFormatStringDescription = [
+ 'Variables are inserted using %{variable}, for example "y: %{y}".',
+ 'Numbers are formatted using d3-format\'s syntax %{variable:d3-format}, for example "Price: %{y:$.2f}".',
+ FORMAT_LINK,
+ 'for details on the formatting syntax.',
+ 'Dates are formatted using d3-time-format\'s syntax %{variable|d3-time-format}, for example "Day: %{2019-01-01|%A}".',
+ DATE_FORMAT_LINK,
+ 'for details on the date formatting syntax.'
+].join(' ');
+
+function describeVariables(extra) {
+ var descPart = extra.description ? ' ' + extra.description : '';
+ var keys = extra.keys || [];
+ if(keys.length > 0) {
+ var quotedKeys = [];
+ for(var i = 0; i < keys.length; i++) {
+ quotedKeys[i] = '`' + keys[i] + '`';
+ }
+ descPart = descPart + 'Finally, the template string has access to ';
+ if(keys.length === 1) {
+ descPart = 'variable ' + quotedKeys[0];
+ } else {
+ descPart = 'variables ' + quotedKeys.slice(0, -1).join(', ') + ' and ' + quotedKeys.slice(-1) + '.';
+ }
+ }
+ return descPart;
+}
+
+exports.hovertemplateAttrs = function(opts, extra) {
+ opts = opts || {};
+ extra = extra || {};
+
+ var descPart = describeVariables(extra);
+
+ var hovertemplate = {
+ valType: 'string',
+
+ dflt: '',
+ editType: opts.editType || 'none',
+
+ };
+
+ if(opts.arrayOk !== false) {
+ hovertemplate.arrayOk = true;
+ }
+
+ return hovertemplate;
+};
+
+exports.texttemplateAttrs = function(opts, extra) {
+ opts = opts || {};
+ extra = extra || {};
+
+ var descPart = describeVariables(extra);
+
+ var texttemplate = {
+ valType: 'string',
+
+ dflt: '',
+ editType: opts.editType || 'calc',
+
+ };
+
+ if(opts.arrayOk !== false) {
+ texttemplate.arrayOk = true;
+ }
+ return texttemplate;
+};
+
+},{"../constants/docs":146}],254:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -65181,7 +65739,7 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout)
}
};
-},{"../../lib":168,"../../plots/get_data":240,"./layout_attributes":253,"./layout_defaults":254,"./ternary":255}],253:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/get_data":241,"./layout_attributes":255,"./layout_defaults":256,"./ternary":257}],255:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -65200,7 +65758,11 @@ var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll;
var extendFlat = _dereq_('../../lib/extend').extendFlat;
var ternaryAxesAttrs = {
- title: axesAttrs.title,
+ title: {
+ text: axesAttrs.title.text,
+ font: axesAttrs.title.font
+ // TODO does standoff here make sense?
+ },
color: axesAttrs.color,
// ticks
tickmode: axesAttrs.tickmode,
@@ -65284,7 +65846,7 @@ attrs.aaxis.uirevision = attrs.baxis.uirevision = attrs.caxis.uirevision = {
};
-},{"../../components/color/attributes":50,"../../lib/extend":162,"../../plot_api/edit_types":195,"../cartesian/layout_attributes":224,"../domain":237}],254:[function(_dereq_,module,exports){
+},{"../../components/color/attributes":50,"../../lib/extend":164,"../../plot_api/edit_types":196,"../cartesian/layout_attributes":225,"../domain":238}],256:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -65416,7 +65978,7 @@ function handleAxisDefaults(containerIn, containerOut, options, ternaryLayoutOut
coerce('layer');
}
-},{"../../components/color":51,"../../lib":168,"../../plot_api/plot_template":202,"../cartesian/line_grid_defaults":226,"../cartesian/tick_label_defaults":231,"../cartesian/tick_mark_defaults":232,"../cartesian/tick_value_defaults":233,"../subplot_defaults":251,"./layout_attributes":253}],255:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../lib":169,"../../plot_api/plot_template":203,"../cartesian/line_grid_defaults":227,"../cartesian/tick_label_defaults":232,"../cartesian/tick_mark_defaults":233,"../cartesian/tick_value_defaults":234,"../subplot_defaults":252,"./layout_attributes":255}],257:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -66173,7 +66735,7 @@ function removeZoombox(gd) {
.remove();
}
-},{"../../components/color":51,"../../components/dragelement":69,"../../components/drawing":72,"../../components/fx":90,"../../components/titles":139,"../../lib":168,"../../lib/extend":162,"../../registry":256,"../cartesian/axes":212,"../cartesian/constants":218,"../cartesian/select":229,"../cartesian/set_convert":230,"../plots":244,"d3":16,"tinycolor2":34}],256:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../components/dragelement":69,"../../components/drawing":72,"../../components/fx":89,"../../components/titles":138,"../../lib":169,"../../lib/extend":164,"../../registry":258,"../cartesian/axes":213,"../cartesian/constants":219,"../cartesian/select":230,"../cartesian/set_convert":231,"../plots":245,"d3":16,"tinycolor2":34}],258:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -66188,6 +66750,7 @@ 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');
@@ -66443,6 +67006,26 @@ function registerTraceModule(_module) {
if(_module.layoutAttributes) {
extendFlat(exports.traceLayoutAttributes, _module.layoutAttributes);
}
+
+ var basePlotModule = _module.basePlotModule;
+ var bpmName = basePlotModule.name;
+
+ // add mapbox-gl CSS here to avoid console warning on instantiation
+ if(bpmName === 'mapbox') {
+ var styleRules = basePlotModule.constants.styleRules;
+ for(var k in styleRules) {
+ addStyleRule('.js-plotly-plot .plotly .mapboxgl-' + k, styleRules[k]);
+ }
+ }
+
+ // if `plotly-geo-assets.js` is not included,
+ // add `PlotlyGeoAssets` global to stash references to all fetched
+ // topojson / geojson data
+ if((bpmName === 'geo' || bpmName === 'mapbox') &&
+ (typeof window !== undefined && window.PlotlyGeoAssets === undefined)
+ ) {
+ window.PlotlyGeoAssets = {topojson: {}};
+ }
}
function registerSubplot(_module) {
@@ -66618,7 +67201,7 @@ function getTraceType(traceType) {
return traceType;
}
-},{"./lib/extend":162,"./lib/is_plain_object":169,"./lib/loggers":172,"./lib/noop":177,"./lib/push_unique":181,"./plots/attributes":209,"./plots/layout_attributes":242}],257:[function(_dereq_,module,exports){
+},{"./lib/dom":162,"./lib/extend":164,"./lib/is_plain_object":170,"./lib/loggers":173,"./lib/noop":178,"./lib/push_unique":182,"./plots/attributes":210,"./plots/layout_attributes":243}],259:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -66791,7 +67374,7 @@ module.exports = function clonePlot(graphObj, options) {
return plotTile;
};
-},{"../lib":168,"../registry":256}],258:[function(_dereq_,module,exports){
+},{"../lib":169,"../registry":258}],260:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -66802,27 +67385,30 @@ module.exports = function clonePlot(graphObj, options) {
'use strict';
-var toImage = _dereq_('../plot_api/to_image');
var Lib = _dereq_('../lib');
-var fileSaver = _dereq_('./filesaver');
-/** Plotly.downloadImage
+var toImage = _dereq_('../plot_api/to_image');
+
+var fileSaver = _dereq_('./filesaver');
+var helpers = _dereq_('./helpers');
+
+/**
+ * Plotly.downloadImage
*
* @param {object | string | HTML div} gd
* can either be a data/layout/config object
* or an existing graph
* or an id to an existing graph
- * @param {object} opts (see ../plot_api/to_image)
+ * @param {object} opts (see Plotly.toImage in ../plot_api/to_image)
* @return {promise}
*/
function downloadImage(gd, opts) {
var _gd;
if(!Lib.isPlainObject(gd)) _gd = Lib.getGraphDiv(gd);
- // check for undefined opts
opts = opts || {};
- // default to png
opts.format = opts.format || 'png';
+ opts.imageDataOnly = true;
return new Promise(function(resolve, reject) {
if(_gd && _gd._snapshotInProgress) {
@@ -66835,7 +67421,7 @@ function downloadImage(gd, opts) {
// does not allow toDataURL
// svg format will work though
if(Lib.isIE() && opts.format !== 'svg') {
- reject(new Error('Sorry IE does not support downloading from canvas. Try {format:\'svg\'} instead.'));
+ reject(new Error(helpers.MSG_IE_BAD_FORMAT));
}
if(_gd) _gd._snapshotInProgress = true;
@@ -66846,7 +67432,7 @@ function downloadImage(gd, opts) {
promise.then(function(result) {
if(_gd) _gd._snapshotInProgress = false;
- return fileSaver(result, filename);
+ return fileSaver(result, filename, opts.format);
}).then(function(name) {
resolve(name);
}).catch(function(err) {
@@ -66858,7 +67444,7 @@ function downloadImage(gd, opts) {
module.exports = downloadImage;
-},{"../lib":168,"../plot_api/to_image":205,"./filesaver":259}],259:[function(_dereq_,module,exports){
+},{"../lib":169,"../plot_api/to_image":206,"./filesaver":261,"./helpers":262}],261:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -66867,6 +67453,11 @@ module.exports = downloadImage;
* LICENSE file in the root directory of this source tree.
*/
+'use strict';
+
+var Lib = _dereq_('../lib');
+var helpers = _dereq_('./helpers');
+
/*
* substantial portions of this code from FileSaver.js
* https://github.com/eligrey/FileSaver.js
@@ -66879,58 +67470,61 @@ module.exports = downloadImage;
* License: MIT
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
*/
-
-'use strict';
-
-var fileSaver = function(url, name) {
+function fileSaver(url, name, format) {
var saveLink = document.createElement('a');
var canUseSaveLink = 'download' in saveLink;
- var isSafari = /Version\/[\d\.]+.*Safari/.test(navigator.userAgent);
+
var promise = new Promise(function(resolve, reject) {
- // IE <10 is explicitly unsupported
- if(typeof navigator !== 'undefined' && /MSIE [1-9]\./.test(navigator.userAgent)) {
+ var blob;
+ var objectUrl;
+
+ if(Lib.isIE9orBelow()) {
reject(new Error('IE < 10 unsupported'));
}
- // First try a.download, then web filesystem, then object URLs
- if(isSafari) {
- // Safari doesn't allow downloading of blob urls
- document.location.href = 'data:application/octet-stream' + url.slice(url.search(/[,;]/));
- resolve(name);
- }
-
- if(!name) {
- name = 'download';
- }
-
- if(canUseSaveLink) {
- saveLink.href = url;
- saveLink.download = name;
- document.body.appendChild(saveLink);
- saveLink.click();
- document.body.removeChild(saveLink);
- resolve(name);
+ // Safari doesn't allow downloading of blob urls
+ if(Lib.isSafari()) {
+ var prefix = format === 'svg' ? ',' : ';base64,';
+ helpers.octetStream(prefix + encodeURIComponent(url));
+ return resolve(name);
}
// IE 10+ (native saveAs)
- if(typeof navigator !== 'undefined' && navigator.msSaveBlob) {
- // At this point we are only dealing with a SVG encoded as
+ if(Lib.isIE()) {
+ // At this point we are only dealing with a decoded SVG as
// a data URL (since IE only supports SVG)
- var encoded = url.split(/^data:image\/svg\+xml,/)[1];
- var svg = decodeURIComponent(encoded);
- navigator.msSaveBlob(new Blob([svg]), name);
- resolve(name);
+ blob = 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;
-},{}],260:[function(_dereq_,module,exports){
+},{"../lib":169,"./helpers":262}],262:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -66965,7 +67559,49 @@ exports.getRedrawFunc = function(gd) {
};
};
-},{"../registry":256}],261:[function(_dereq_,module,exports){
+exports.encodeSVG = function(svg) {
+ return 'data:image/svg+xml,' + encodeURIComponent(svg);
+};
+
+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 {
+ 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
+function fixBinary(b) {
+ var len = b.length;
+ var buf = new ArrayBuffer(len);
+ var arr = new Uint8Array(buf);
+ for(var i = 0; i < len; i++) {
+ arr[i] = b.charCodeAt(i);
+ }
+ return buf;
+}
+
+exports.IMAGE_URL_PREFIX = /^data:image\/\w+;base64,/;
+
+exports.MSG_IE_BAD_FORMAT = 'Sorry IE does not support downloading from canvas. Try {format:\'svg\'} instead.';
+
+},{"../registry":258}],263:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -66991,7 +67627,7 @@ var Snapshot = {
module.exports = Snapshot;
-},{"./cloneplot":257,"./download":258,"./helpers":260,"./svgtoimg":262,"./toimage":263,"./tosvg":264}],262:[function(_dereq_,module,exports){
+},{"./cloneplot":259,"./download":260,"./helpers":262,"./svgtoimg":264,"./toimage":265,"./tosvg":266}],264:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -67005,6 +67641,8 @@ module.exports = Snapshot;
var Lib = _dereq_('../lib');
var EventEmitter = _dereq_('events').EventEmitter;
+var helpers = _dereq_('./helpers');
+
function svgToImg(opts) {
var ev = opts.emitter || new EventEmitter();
@@ -67015,7 +67653,7 @@ function svgToImg(opts) {
// IE only support svg
if(Lib.isIE() && format !== 'svg') {
- var ieSvgError = new Error('Sorry IE does not support downloading from canvas. Try {format:\'svg\'} instead.');
+ var ieSvgError = new Error(helpers.MSG_IE_BAD_FORMAT);
reject(ieSvgError);
// eventually remove the ev
// in favor of promises
@@ -67035,11 +67673,14 @@ function svgToImg(opts) {
var ctx = canvas.getContext('2d');
var img = new Image();
+ var svgBlob, url;
- // for Safari support, eliminate createObjectURL
- // this decision could cause problems if content
- // is not restricted to svg
- var url = 'data:image/svg+xml,' + encodeURIComponent(svg);
+ if(format === 'svg' || Lib.isIE9orBelow() || Lib.isSafari()) {
+ url = helpers.encodeSVG(svg);
+ } else {
+ svgBlob = helpers.createBlob(svg, 'svg');
+ url = helpers.createObjectURL(svgBlob);
+ }
canvas.width = w1;
canvas.height = h1;
@@ -67047,6 +67688,9 @@ function svgToImg(opts) {
img.onload = function() {
var imgData;
+ svgBlob = null;
+ helpers.revokeObjectURL(url);
+
// don't need to draw to canvas if svg
// save some time and also avoid failure on IE
if(format !== 'svg') {
@@ -67084,6 +67728,9 @@ function svgToImg(opts) {
};
img.onerror = function(err) {
+ svgBlob = null;
+ helpers.revokeObjectURL(url);
+
reject(err);
// eventually remove the ev
// in favor of promises
@@ -67107,7 +67754,7 @@ function svgToImg(opts) {
module.exports = svgToImg;
-},{"../lib":168,"events":15}],263:[function(_dereq_,module,exports){
+},{"../lib":169,"./helpers":262,"events":15}],265:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -67184,7 +67831,7 @@ function toImage(gd, opts) {
module.exports = toImage;
-},{"../lib":168,"../registry":256,"./cloneplot":257,"./helpers":260,"./svgtoimg":262,"./tosvg":264,"events":15}],264:[function(_dereq_,module,exports){
+},{"../lib":169,"../registry":258,"./cloneplot":259,"./helpers":262,"./svgtoimg":264,"./tosvg":266,"events":15}],266:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -67365,7 +68012,7 @@ module.exports = function toSVG(gd, format, scale) {
return s;
};
-},{"../components/color":51,"../components/drawing":72,"../constants/xmlns_namespaces":150,"../lib":168,"d3":16}],265:[function(_dereq_,module,exports){
+},{"../components/color":51,"../components/drawing":72,"../constants/xmlns_namespaces":150,"../lib":169,"d3":16}],267:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -67376,29 +68023,29 @@ module.exports = function toSVG(gd, format, scale) {
'use strict';
-var mergeArray = _dereq_('../../lib').mergeArray;
+var Lib = _dereq_('../../lib');
// arrayOk attributes, merge them into calcdata array
module.exports = function arraysToCalcdata(cd, trace) {
for(var i = 0; i < cd.length; i++) cd[i].i = i;
- mergeArray(trace.text, cd, 'tx');
- mergeArray(trace.hovertext, cd, 'htx');
+ Lib.mergeArray(trace.text, cd, 'tx');
+ Lib.mergeArray(trace.hovertext, cd, 'htx');
var marker = trace.marker;
if(marker) {
- mergeArray(marker.opacity, cd, 'mo');
- mergeArray(marker.color, cd, 'mc');
+ Lib.mergeArray(marker.opacity, cd, 'mo', true);
+ Lib.mergeArray(marker.color, cd, 'mc');
var markerLine = marker.line;
if(markerLine) {
- mergeArray(markerLine.color, cd, 'mlc');
- mergeArray(markerLine.width, cd, 'mlw');
+ Lib.mergeArray(markerLine.color, cd, 'mlc');
+ Lib.mergeArrayCastPositive(markerLine.width, cd, 'mlw');
}
}
};
-},{"../../lib":168}],266:[function(_dereq_,module,exports){
+},{"../../lib":169}],268:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -67410,10 +68057,11 @@ module.exports = function arraysToCalcdata(cd, trace) {
'use strict';
var scatterAttrs = _dereq_('../scatter/attributes');
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
+var hovertemplateAttrs = _dereq_('../../plots/template_attributes').hovertemplateAttrs;
+var texttemplateAttrs = _dereq_('../../plots/template_attributes').texttemplateAttrs;
var colorScaleAttrs = _dereq_('../../components/colorscale/attributes');
var fontAttrs = _dereq_('../../plots/font_attributes');
-var constants = _dereq_('./constants.js');
+var constants = _dereq_('./constants');
var extendFlat = _dereq_('../../lib/extend').extendFlat;
@@ -67460,6 +68108,9 @@ module.exports = {
dy: scatterAttrs.dy,
text: scatterAttrs.text,
+ texttemplate: texttemplateAttrs({editType: 'plot'}, {
+ keys: constants.eventDataKeys
+ }),
hovertext: scatterAttrs.hovertext,
hovertemplate: hovertemplateAttrs({}, {
keys: constants.eventDataKeys
@@ -67603,7 +68254,7 @@ module.exports = {
}
};
-},{"../../components/colorscale/attributes":58,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../../plots/font_attributes":238,"../scatter/attributes":365,"./constants.js":268}],267:[function(_dereq_,module,exports){
+},{"../../components/colorscale/attributes":58,"../../lib/extend":164,"../../plots/font_attributes":239,"../../plots/template_attributes":253,"../scatter/attributes":377,"./constants":270}],269:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -67668,7 +68319,7 @@ module.exports = function calc(gd, trace) {
return cd;
};
-},{"../../components/colorscale/calc":59,"../../components/colorscale/helpers":62,"../../plots/cartesian/axes":212,"../scatter/calc_selection":367,"./arrays_to_calcdata":265}],268:[function(_dereq_,module,exports){
+},{"../../components/colorscale/calc":59,"../../components/colorscale/helpers":62,"../../plots/cartesian/axes":213,"../scatter/calc_selection":379,"./arrays_to_calcdata":267}],270:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -67681,10 +68332,16 @@ module.exports = function calc(gd, trace) {
'use strict';
module.exports = {
- eventDataKeys: []
+ // padding in pixels around text
+ TEXTPAD: 3,
+ // 'value' and 'label' are not really necessary for bar traces,
+ // but they were made available to `texttemplate` (maybe by accident)
+ // via tokens `%{value}` and `%{label}` starting in 1.50.0,
+ // so let's include them in the event data also.
+ eventDataKeys: ['value', 'label']
};
-},{}],269:[function(_dereq_,module,exports){
+},{}],271:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -68452,7 +69109,7 @@ module.exports = {
setGroupPositions: setGroupPositions
};
-},{"../../constants/numerical":149,"../../lib":168,"../../plots/cartesian/axes":212,"../../plots/cartesian/axis_ids":215,"../../registry":256,"./sieve.js":278,"fast-isnumeric":18}],270:[function(_dereq_,module,exports){
+},{"../../constants/numerical":149,"../../lib":169,"../../plots/cartesian/axes":213,"../../plots/cartesian/axis_ids":216,"../../registry":258,"./sieve.js":281,"fast-isnumeric":18}],272:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -68610,6 +69267,8 @@ function handleText(traceIn, traceOut, layout, coerce, textposition, opts) {
if(moduleHasConstrain) coerce('constraintext');
if(moduleHasCliponaxis) coerce('cliponaxis');
if(moduleHasTextangle) coerce('textangle');
+
+ coerce('texttemplate');
}
if(hasInside) {
@@ -68624,7 +69283,36 @@ module.exports = {
handleText: handleText
};
-},{"../../components/color":51,"../../lib":168,"../../plots/cartesian/axis_ids":215,"../../registry":256,"../scatter/xy_defaults":390,"./attributes":266,"./style_defaults":280}],271:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../lib":169,"../../plots/cartesian/axis_ids":216,"../../registry":258,"../scatter/xy_defaults":403,"./attributes":268,"./style_defaults":283}],273:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+module.exports = function eventData(out, pt, trace) {
+ // standard cartesian event data
+ out.x = 'xVal' in pt ? pt.xVal : pt.x;
+ out.y = 'yVal' in pt ? pt.yVal : pt.y;
+ if(pt.xa) out.xaxis = pt.xa;
+ if(pt.ya) out.yaxis = pt.ya;
+
+ if(trace.orientation === 'h') {
+ out.label = out.y;
+ out.value = out.x;
+ } else {
+ out.label = out.x;
+ out.value = out.y;
+ }
+
+ return out;
+};
+
+},{}],274:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -68637,6 +69325,7 @@ module.exports = {
var isNumeric = _dereq_('fast-isnumeric');
var tinycolor = _dereq_('tinycolor2');
+var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray;
exports.coerceString = function(attributeDefinition, value, defaultValue) {
if(typeof value === 'string') {
@@ -68692,7 +69381,16 @@ exports.getValue = function(arrayOrScalar, index) {
return value;
};
-},{"fast-isnumeric":18,"tinycolor2":34}],272:[function(_dereq_,module,exports){
+exports.getLineWidth = function(trace, di) {
+ var w =
+ (0 < di.mlw) ? di.mlw :
+ !isArrayOrTypedArray(trace.marker.line.width) ? trace.marker.line.width :
+ 0;
+
+ return w;
+};
+
+},{"../../lib":169,"fast-isnumeric":18,"tinycolor2":34}],275:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -68709,6 +69407,8 @@ var Registry = _dereq_('../../registry');
var Color = _dereq_('../../components/color');
var fillText = _dereq_('../../lib').fillText;
+var getLineWidth = _dereq_('./helpers').getLineWidth;
+var hoverLabelText = _dereq_('../../plots/cartesian/axes').hoverLabelText;
function hoverPoints(pointData, xval, yval, hovermode) {
var barPointData = hoverOnBars(pointData, xval, yval, hovermode);
@@ -68845,6 +69545,9 @@ function hoverOnBars(pointData, xval, yval, hovermode) {
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
pointData.spikeDistance = (sizeFn(di) + thisBarPositionFn(di)) / 2 + maxSpikeDistance - maxHoverDistance;
// they also want to point to the data value, regardless of where the label goes
@@ -68860,7 +69563,7 @@ function hoverOnBars(pointData, xval, yval, hovermode) {
function getTraceColor(trace, di) {
var mc = di.mcc || trace.marker.color;
var mlc = di.mlcc || trace.marker.line.color;
- var mlw = di.mlw || trace.marker.line.width;
+ var mlw = getLineWidth(trace, di);
if(Color.opacity(mc)) return mc;
else if(Color.opacity(mlc) && mlw) return mlc;
@@ -68872,7 +69575,7 @@ module.exports = {
getTraceColor: getTraceColor
};
-},{"../../components/color":51,"../../components/fx":90,"../../lib":168,"../../registry":256}],273:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../components/fx":89,"../../lib":169,"../../plots/cartesian/axes":213,"../../registry":258,"./helpers":274}],276:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -68897,18 +69600,20 @@ module.exports = {
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":223,"../scatter/marker_colorbar":382,"./arrays_to_calcdata":265,"./attributes":266,"./calc":267,"./cross_trace_calc":269,"./defaults":270,"./hover":272,"./layout_attributes":274,"./layout_defaults":275,"./plot":276,"./select":277,"./style":279}],274:[function(_dereq_,module,exports){
+},{"../../plots/cartesian":224,"../scatter/marker_colorbar":395,"./arrays_to_calcdata":267,"./attributes":268,"./calc":269,"./cross_trace_calc":271,"./defaults":272,"./event_data":273,"./hover":275,"./layout_attributes":277,"./layout_defaults":278,"./plot":279,"./select":280,"./style":282}],277:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -68956,7 +69661,7 @@ module.exports = {
}
};
-},{}],275:[function(_dereq_,module,exports){
+},{}],278:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -69016,7 +69721,7 @@ module.exports = function(layoutIn, layoutOut, fullData) {
coerce('bargroupgap');
};
-},{"../../lib":168,"../../plots/cartesian/axes":212,"../../registry":256,"./layout_attributes":274}],276:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/cartesian/axes":213,"../../registry":258,"./layout_attributes":277}],279:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -69040,13 +69745,22 @@ var tickText = _dereq_('../../plots/cartesian/axes').tickText;
var style = _dereq_('./style');
var helpers = _dereq_('./helpers');
+var constants = _dereq_('./constants');
var attributes = _dereq_('./attributes');
var attributeText = attributes.text;
var attributeTextPosition = attributes.textposition;
-// padding in pixels around text
-var TEXTPAD = 3;
+var appendArrayPointValue = _dereq_('../../components/fx/helpers').appendArrayPointValue;
+
+var TEXTPAD = constants.TEXTPAD;
+
+function keyFunc(d) {return d.id;}
+function getKeyFunc(trace) {
+ if(trace.ids) {
+ return keyFunc;
+ }
+}
function dirSign(a, b) {
return (a < b) ? 1 : -1;
@@ -69068,7 +69782,28 @@ function getXY(di, xa, ya, isHorizontal) {
return isHorizontal ? [s, p] : [p, s];
}
-function plot(gd, plotinfo, cdModule, traceLayer, opts) {
+function transition(selection, opts, makeOnCompleteCallback) {
+ if(hasTransition(opts)) {
+ var onComplete;
+ if(makeOnCompleteCallback) {
+ onComplete = makeOnCompleteCallback();
+ }
+ return selection
+ .transition()
+ .duration(opts.duration)
+ .ease(opts.easing)
+ .each('end', function() { onComplete && onComplete(); })
+ .each('interrupt', function() { onComplete && onComplete(); });
+ } else {
+ return selection;
+ }
+}
+
+function hasTransition(transitionOpts) {
+ return transitionOpts && transitionOpts.duration > 0;
+}
+
+function plot(gd, plotinfo, cdModule, traceLayer, opts, makeOnCompleteCallback) {
var xa = plotinfo.xaxis;
var ya = plotinfo.yaxis;
var fullLayout = gd._fullLayout;
@@ -69088,7 +69823,7 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts) {
var isWaterfall = (trace.type === 'waterfall');
var isFunnel = (trace.type === 'funnel');
var isBar = (trace.type === 'bar');
- var shouldDisplayZeros = isBar || isFunnel;
+ var shouldDisplayZeros = (isBar || isFunnel);
var adjustPixel = 0;
if(isWaterfall && trace.connector.visible && trace.connector.mode === 'between') {
@@ -69097,11 +69832,10 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts) {
var isHorizontal = (trace.orientation === 'h');
- if(!plotinfo.isRangePlot) cd[0].node3 = plotGroup;
-
var pointGroup = Lib.ensureSingle(plotGroup, 'g', 'points');
- var bars = pointGroup.selectAll('g.point').data(Lib.identity);
+ var keyFunc = getKeyFunc(trace);
+ var bars = pointGroup.selectAll('g.point').data(Lib.identity, keyFunc);
bars.enter().append('g')
.classed('point', true);
@@ -69115,7 +69849,6 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts) {
// clipped xf/yf (2nd arg true): non-positive
// log values go off-screen by plotwidth
// so you see them continue if you drag the plot
-
var xy = getXY(di, xa, ya, isHorizontal);
var x0 = xy[0][0];
@@ -69123,15 +69856,25 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts) {
var y0 = xy[1][0];
var y1 = xy[1][1];
- var isBlank = di.isBlank = !(
- isNumeric(x0) && isNumeric(x1) &&
- isNumeric(y0) && isNumeric(y1) &&
- (x0 !== x1 || (shouldDisplayZeros && isHorizontal)) &&
- (y0 !== y1 || (shouldDisplayZeros && !isHorizontal))
+ var isBlank = (
+ x0 === x1 ||
+ y0 === y1 ||
+ !isNumeric(x0) ||
+ !isNumeric(x1) ||
+ !isNumeric(y0) ||
+ !isNumeric(y1)
);
+ // display zeros if line.width > 0
+ if(isBlank && shouldDisplayZeros && helpers.getLineWidth(trace, di) && (isHorizontal ? x1 - x0 === 0 : y1 - y0 === 0)) {
+ isBlank = false;
+ }
+ di.isBlank = isBlank;
+
+ if(isBlank && isHorizontal) x1 = x0;
+ if(isBlank && !isHorizontal) y1 = y0;
// in waterfall mode `between` we need to adjust bar end points to match the connector width
- if(adjustPixel) {
+ if(adjustPixel && !isBlank) {
if(isHorizontal) {
x0 -= dirSign(x0, x1) * adjustPixel;
x1 += dirSign(x0, x1) * adjustPixel;
@@ -69151,8 +69894,7 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts) {
mc = cont.color;
}
} else {
- lw = (di.mlw + 1 || trace.marker.line.width + 1 ||
- (di.trace ? di.trace.marker.line.width : 0) + 1) - 1;
+ lw = helpers.getLineWidth(trace, di);
mc = di.mc || trace.marker.color;
}
@@ -69191,12 +69933,18 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts) {
y1 = fixpx(y1, y0);
}
- Lib.ensureSingle(bar, 'path')
+ var sel = transition(Lib.ensureSingle(bar, 'path'), opts, makeOnCompleteCallback);
+ sel
.style('vector-effect', 'non-scaling-stroke')
- .attr('d', isBlank ? 'M0,0Z' : 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z')
+ .attr('d', 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z')
.call(Drawing.setClipUrl, plotinfo.layerClipId, gd);
- appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, opts);
+ if(hasTransition(opts)) {
+ 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);
@@ -69210,10 +69958,10 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts) {
});
// error bars are on the top
- Registry.getComponentMethod('errorbars', 'plot')(gd, bartraces, plotinfo);
+ Registry.getComponentMethod('errorbars', 'plot')(gd, bartraces, plotinfo, opts);
}
-function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts) {
+function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts, makeOnCompleteCallback) {
var xa = plotinfo.xaxis;
var ya = plotinfo.yaxis;
@@ -69225,7 +69973,6 @@ function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts) {
.text(text)
.attr({
'class': 'bartext bartext-' + textPosition,
- transform: '',
'text-anchor': 'middle',
// prohibit tex interpretation until we can handle
// tex and regular text together
@@ -69241,7 +69988,7 @@ function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts) {
var trace = calcTrace[0].trace;
var isHorizontal = (trace.orientation === 'h');
- var text = getText(calcTrace, i, xa, ya);
+ var text = getText(fullLayout, calcTrace, i, xa, ya);
textPosition = getTextPosition(trace, i);
// compute text position
@@ -69338,9 +70085,12 @@ function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts) {
(textPosition === 'outside') ?
outsideTextFont : insideTextFont);
+ 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();
@@ -69355,32 +70105,32 @@ function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts) {
trace.constraintext === 'both' ||
trace.constraintext === 'outside';
- transform = getTransformToMoveOutsideBar(x0, x1, y0, y1, textBB, {
+ transform = Lib.getTextTransform(toMoveOutsideBar(x0, x1, y0, y1, textBB, {
isHorizontal: isHorizontal,
constrained: constrained,
angle: trace.textangle
- });
+ }));
} else {
constrained =
trace.constraintext === 'both' ||
trace.constraintext === 'inside';
- transform = getTransformToMoveInsideBar(x0, x1, y0, y1, textBB, {
+ transform = Lib.getTextTransform(toMoveInsideBar(x0, x1, y0, y1, textBB, {
isHorizontal: isHorizontal,
constrained: constrained,
angle: trace.textangle,
anchor: trace.insidetextanchor
- });
+ }));
}
- textSelection.attr('transform', transform);
+ transition(textSelection, opts, makeOnCompleteCallback).attr('transform', transform);
}
-function getRotationFromAngle(angle) {
+function getRotateFromAngle(angle) {
return (angle === 'auto') ? 0 : angle;
}
-function getTransformToMoveInsideBar(x0, x1, y0, y1, textBB, opts) {
+function toMoveInsideBar(x0, x1, y0, y1, textBB, opts) {
var isHorizontal = !!opts.isHorizontal;
var constrained = !!opts.constrained;
var angle = opts.angle || 0;
@@ -69417,9 +70167,9 @@ function getTransformToMoveInsideBar(x0, x1, y0, y1, textBB, opts) {
lx = tmp;
}
- var rotation = getRotationFromAngle(angle);
- var absSin = Math.abs(Math.sin(Math.PI / 180 * rotation));
- var absCos = Math.abs(Math.cos(Math.PI / 180 * rotation));
+ var rotate = getRotateFromAngle(angle);
+ var absSin = Math.abs(Math.sin(Math.PI / 180 * rotate));
+ var absCos = Math.abs(Math.cos(Math.PI / 180 * rotate));
// compute and apply text padding
var dx = Math.max(lx * absCos, ly * absSin);
@@ -69453,12 +70203,19 @@ function getTransformToMoveInsideBar(x0, x1, y0, y1, textBB, opts) {
var textY = (textBB.top + textBB.bottom) / 2;
// lastly apply auto rotation
- if(isAutoRotated) rotation += 90;
+ if(isAutoRotated) rotate += 90;
- return getTransform(textX, textY, targetX, targetY, scale, rotation);
+ return {
+ textX: textX,
+ textY: textY,
+ targetX: targetX,
+ targetY: targetY,
+ scale: scale,
+ rotate: rotate
+ };
}
-function getTransformToMoveOutsideBar(x0, x1, y0, y1, textBB, opts) {
+function toMoveOutsideBar(x0, x1, y0, y1, textBB, opts) {
var isHorizontal = !!opts.isHorizontal;
var constrained = !!opts.constrained;
var angle = opts.angle || 0;
@@ -69477,7 +70234,7 @@ function getTransformToMoveOutsideBar(x0, x1, y0, y1, textBB, opts) {
textpad = (lx > 2 * TEXTPAD) ? TEXTPAD : 0;
}
- // compute rotation and scale
+ // compute rotate and scale
var scale = 1;
if(constrained) {
scale = (isHorizontal) ?
@@ -69485,9 +70242,9 @@ function getTransformToMoveOutsideBar(x0, x1, y0, y1, textBB, opts) {
Math.min(1, lx / textWidth);
}
- var rotation = getRotationFromAngle(angle);
- var absSin = Math.abs(Math.sin(Math.PI / 180 * rotation));
- var absCos = Math.abs(Math.cos(Math.PI / 180 * rotation));
+ var rotate = getRotateFromAngle(angle);
+ var absSin = Math.abs(Math.sin(Math.PI / 180 * rotate));
+ var absCos = Math.abs(Math.cos(Math.PI / 180 * rotate));
// compute text and target positions
var targetWidth = scale * (isHorizontal ? textHeight : textWidth);
@@ -69506,39 +70263,27 @@ function getTransformToMoveOutsideBar(x0, x1, y0, y1, textBB, opts) {
var textX = (textBB.left + textBB.right) / 2;
var textY = (textBB.top + textBB.bottom) / 2;
- return getTransform(textX, textY, targetX, targetY, scale, rotation);
+ return {
+ textX: textX,
+ textY: textY,
+ targetX: targetX,
+ targetY: targetY,
+ scale: scale,
+ rotate: rotate
+ };
}
-function getTransform(textX, textY, targetX, targetY, scale, rotation) {
- var transformScale;
- var transformRotate;
- var transformTranslate;
-
- if(scale < 1) transformScale = 'scale(' + scale + ') ';
- else {
- scale = 1;
- transformScale = '';
- }
-
- transformRotate = (rotation) ?
- 'rotate(' + rotation + ' ' + textX + ' ' + textY + ') ' : '';
-
- // Note that scaling also affects the center of the text box
- var translateX = (targetX - scale * textX);
- var translateY = (targetY - scale * textY);
- transformTranslate = 'translate(' + translateX + ' ' + translateY + ')';
-
- return transformTranslate + transformScale + transformRotate;
-}
-
-function getText(calcTrace, index, xa, ya) {
+function getText(fullLayout, calcTrace, index, xa, ya) {
var trace = calcTrace[0].trace;
+ var texttemplate = trace.texttemplate;
var value;
- if(!trace.textinfo) {
- value = helpers.getValue(trace.text, index);
- } else {
+ if(texttemplate) {
+ value = calcTexttemplate(fullLayout, calcTrace, index, xa, ya);
+ } else if(trace.textinfo) {
value = calcTextinfo(calcTrace, index, xa, ya);
+ } else {
+ value = helpers.getValue(trace.text, index);
}
return helpers.coerceString(attributeText, value);
@@ -69549,6 +70294,76 @@ function getTextPosition(trace, index) {
return helpers.coerceEnumerated(attributeTextPosition, value);
}
+function calcTexttemplate(fullLayout, calcTrace, index, xa, ya) {
+ var trace = calcTrace[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 = calcTrace[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(calcTrace, index, xa, ya) {
var trace = calcTrace[0].trace;
var isHorizontal = (trace.orientation === 'h');
@@ -69625,11 +70440,11 @@ function calcTextinfo(calcTrace, index, xa, ya) {
module.exports = {
plot: plot,
- getTransformToMoveInsideBar: getTransformToMoveInsideBar,
- getTransformToMoveOutsideBar: getTransformToMoveOutsideBar
+ toMoveInsideBar: toMoveInsideBar,
+ toMoveOutsideBar: toMoveOutsideBar
};
-},{"../../components/color":51,"../../components/drawing":72,"../../lib":168,"../../lib/svg_text_utils":189,"../../plots/cartesian/axes":212,"../../registry":256,"./attributes":266,"./helpers":271,"./style":279,"d3":16,"fast-isnumeric":18}],277:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../components/drawing":72,"../../components/fx/helpers":86,"../../lib":169,"../../lib/svg_text_utils":190,"../../plots/cartesian/axes":213,"../../registry":258,"./attributes":268,"./constants":270,"./helpers":274,"./style":282,"d3":16,"fast-isnumeric":18}],280:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -69693,7 +70508,7 @@ function getCentroid(d, xa, ya, isHorizontal, isFunnel) {
}
}
-},{}],278:[function(_dereq_,module,exports){
+},{}],281:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -69804,7 +70619,7 @@ Sieve.prototype.getLabel = function getLabel(position, value) {
return prefix + label;
};
-},{"../../constants/numerical":149,"../../lib":168}],279:[function(_dereq_,module,exports){
+},{"../../constants/numerical":149,"../../lib":169}],282:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -69827,8 +70642,8 @@ var attributeInsideTextFont = attributes.insidetextfont;
var attributeOutsideTextFont = attributes.outsidetextfont;
var helpers = _dereq_('./helpers');
-function style(gd, cd) {
- var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.barlayer').selectAll('g.trace');
+function style(gd) {
+ var s = d3.select(gd).selectAll('g.barlayer').selectAll('g.trace');
var barcount = s.size();
var fullLayout = gd._fullLayout;
@@ -69869,16 +70684,14 @@ function styleTextPoints(sel, trace, gd) {
});
}
-function styleOnSelect(gd, cd) {
- var s = cd[0].node3;
+function styleOnSelect(gd, cd, sel) {
var trace = cd[0].trace;
if(trace.selectedpoints) {
- stylePointsInSelectionMode(s, trace, gd);
+ stylePointsInSelectionMode(sel, trace, gd);
} else {
- stylePoints(s, trace, gd);
-
- Registry.getComponentMethod('errorbars', 'style')(s);
+ stylePoints(sel, trace, gd);
+ Registry.getComponentMethod('errorbars', 'style')(sel);
}
}
@@ -69983,7 +70796,7 @@ module.exports = {
getBarColor: getBarColor
};
-},{"../../components/color":51,"../../components/drawing":72,"../../lib":168,"../../registry":256,"./attributes":266,"./helpers":271,"d3":16}],280:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../components/drawing":72,"../../lib":169,"../../registry":258,"./attributes":268,"./helpers":274,"d3":16}],283:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -70021,7 +70834,7 @@ module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, default
coerce('unselected.marker.color');
};
-},{"../../components/color":51,"../../components/colorscale/defaults":61,"../../components/colorscale/helpers":62}],281:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../components/colorscale/defaults":61,"../../components/colorscale/helpers":62}],284:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -70035,7 +70848,7 @@ module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, default
var scatterAttrs = _dereq_('../scatter/attributes');
var barAttrs = _dereq_('../bar/attributes');
var colorAttrs = _dereq_('../../components/color/attributes');
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
+var hovertemplateAttrs = _dereq_('../../plots/template_attributes').hovertemplateAttrs;
var extendFlat = _dereq_('../../lib/extend').extendFlat;
var scatterMarkerAttrs = scatterAttrs.marker;
@@ -70233,7 +71046,7 @@ module.exports = {
}
};
-},{"../../components/color/attributes":50,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../bar/attributes":266,"../scatter/attributes":365}],282:[function(_dereq_,module,exports){
+},{"../../components/color/attributes":50,"../../lib/extend":164,"../../plots/template_attributes":253,"../bar/attributes":268,"../scatter/attributes":377}],285:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -70305,6 +71118,9 @@ module.exports = function calc(gd, trace) {
Lib.identity :
function(pt) { return (pt.v < cdi.lf || pt.v > cdi.uf); };
+ var minLowerNotch = Infinity;
+ var maxUpperNotch = -Infinity;
+
// build calcdata trace items, one item per distinct position
for(i = 0; i < pLen; i++) {
if(ptsPerBin[i].length > 0) {
@@ -70359,6 +71175,8 @@ module.exports = function calc(gd, trace) {
var mci = 1.57 * iqr / Math.sqrt(bvLen);
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);
@@ -70367,8 +71185,11 @@ module.exports = function calc(gd, trace) {
}
calcSelection(cd, trace);
- var extremes = Axes.findExtremes(valAxis, val, {padded: true});
- trace._extremes[valAxis._id] = extremes;
+
+ trace._extremes[valAxis._id] = Axes.findExtremes(valAxis,
+ trace.notched ? val.concat([minLowerNotch, maxUpperNotch]) : val,
+ {padded: true}
+ );
if(cd.length > 0) {
cd[0].t = {
@@ -70482,7 +71303,7 @@ function sortByVal(a, b) { return a.v - b.v; }
function extractVal(o) { return o.v; }
-},{"../../lib":168,"../../plots/cartesian/axes":212,"fast-isnumeric":18}],283:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/cartesian/axes":213,"fast-isnumeric":18}],286:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -70545,7 +71366,7 @@ function setPositionOffset(traceType, gd, boxList, posAxis) {
for(i = 0; i < boxList.length; i++) {
calcTrace = calcdata[boxList[i]];
for(j = 0; j < calcTrace.length; j++) {
- pointList.push(calcTrace[j].pos);
+ pointList.push(posAxis.c2l(calcTrace[j].pos, true));
shownPts += (calcTrace[j].pts2 || []).length;
}
}
@@ -70698,6 +71519,7 @@ function setPositionOffset(traceType, gd, boxList, posAxis) {
padded: padded,
vpadminus: vpadminus,
vpadplus: vpadplus,
+ vpadLinearized: true,
// N.B. SVG px-space positive/negative
ppadminus: {x: ppadminus, y: ppadplus}[axLetter],
ppadplus: {x: ppadplus, y: ppadminus}[axLetter],
@@ -70710,7 +71532,7 @@ module.exports = {
setPositionOffset: setPositionOffset
};
-},{"../../lib":168,"../../plots/cartesian/axes":212,"../../plots/cartesian/axis_ids":215}],284:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/cartesian/axes":213,"../../plots/cartesian/axis_ids":216}],287:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -70854,7 +71676,7 @@ module.exports = {
handlePointsDefaults: handlePointsDefaults
};
-},{"../../components/color":51,"../../lib":168,"../../registry":256,"../bar/defaults":270,"./attributes":281}],285:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../lib":169,"../../registry":258,"../bar/defaults":272,"./attributes":284}],288:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -70879,7 +71701,7 @@ module.exports = function eventData(out, pt) {
return out;
};
-},{}],286:[function(_dereq_,module,exports){
+},{}],289:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -70942,7 +71764,7 @@ function hoverOnBoxes(pointData, xval, yval, hovermode) {
var boxDelta = t.bdPos;
var boxDeltaPos, boxDeltaNeg;
var posAcceptance = t.wHover;
- var shiftPos = function(di) { return di.pos + t.bPos - pVal; };
+ var shiftPos = function(di) { return pAxis.c2l(di.pos) + t.bPos - pAxis.c2l(pVal); };
if(isViolin && trace.side !== 'both') {
if(trace.side === 'positive') {
@@ -71033,7 +71855,7 @@ function hoverOnBoxes(pointData, xval, yval, hovermode) {
// box plots: each "point" gets many labels
var usedVals = {};
- var attrs = ['med', 'min', 'q1', 'q3', 'max'];
+ var attrs = ['med', 'q1', 'q3', 'min', 'max'];
if(trace.boxmean || (trace.meanline || {}).visible) {
attrs.push('mean');
@@ -71053,6 +71875,7 @@ function hoverOnBoxes(pointData, xval, yval, hovermode) {
var valPx = vAxis.c2p(val, true);
var pointData2 = Lib.extendFlat({}, pointData);
+ pointData2.attr = attr;
pointData2[vLetter + '0'] = pointData2[vLetter + '1'] = valPx;
pointData2[vLetter + 'LabelVal'] = val;
pointData2[vLetter + 'Label'] = (t.labels ? t.labels[attr] + ' ' : '') + Axes.hoverLabelText(vAxis, val);
@@ -71163,7 +71986,7 @@ module.exports = {
hoverOnPoints: hoverOnPoints
};
-},{"../../components/color":51,"../../components/fx":90,"../../lib":168,"../../plots/cartesian/axes":212}],287:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../components/fx":89,"../../lib":169,"../../plots/cartesian/axes":213}],290:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -71198,7 +72021,7 @@ module.exports = {
}
};
-},{"../../plots/cartesian":223,"./attributes":281,"./calc":282,"./cross_trace_calc":283,"./defaults":284,"./event_data":285,"./hover":286,"./layout_attributes":288,"./layout_defaults":289,"./plot":290,"./select":291,"./style":292}],288:[function(_dereq_,module,exports){
+},{"../../plots/cartesian":224,"./attributes":284,"./calc":285,"./cross_trace_calc":286,"./defaults":287,"./event_data":288,"./hover":289,"./layout_attributes":291,"./layout_defaults":292,"./plot":293,"./select":294,"./style":295}],291:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -71239,7 +72062,7 @@ module.exports = {
}
};
-},{}],289:[function(_dereq_,module,exports){
+},{}],292:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -71285,7 +72108,7 @@ module.exports = {
_supply: _supply
};
-},{"../../lib":168,"../../registry":256,"./layout_attributes":288}],290:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../registry":258,"./layout_attributes":291}],293:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -71314,7 +72137,6 @@ function plot(gd, plotinfo, cdbox, boxLayer) {
var cd0 = cd[0];
var t = cd0.t;
var trace = cd0.trace;
- if(!plotinfo.isRangePlot) cd0.node3 = plotGroup;
// whisker width
t.wdPos = t.bdPos * trace.whiskerwidth;
@@ -71375,14 +72197,14 @@ function plotBoxAndWhiskers(sel, axes, trace, t) {
paths.each(function(d) {
if(d.empty) return 'M0,0Z';
- var pos = d.pos;
- var posc = posAxis.c2p(pos + bPos, true) + bPosPxOffset;
- var pos0 = posAxis.c2p(pos + bPos - bdPos0, true) + bPosPxOffset;
- var pos1 = posAxis.c2p(pos + bPos + bdPos1, true) + bPosPxOffset;
- var posw0 = posAxis.c2p(pos + bPos - wdPos, true) + bPosPxOffset;
- var posw1 = posAxis.c2p(pos + bPos + wdPos, true) + bPosPxOffset;
- var posm0 = posAxis.c2p(pos + bPos - bdPos0 * nw, true) + bPosPxOffset;
- var posm1 = posAxis.c2p(pos + bPos + bdPos1 * nw, true) + bPosPxOffset;
+ 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 posw0 = posAxis.l2p(lcenter - wdPos) + bPosPxOffset;
+ var posw1 = posAxis.l2p(lcenter + wdPos) + bPosPxOffset;
+ var posm0 = posAxis.l2p(lcenter - bdPos0 * nw) + bPosPxOffset;
+ var posm1 = posAxis.l2p(lcenter + bdPos1 * nw) + bPosPxOffset;
var q1 = valAxis.c2p(d.q1, true);
var q3 = valAxis.c2p(d.q3, true);
// make sure median isn't identical to either of the
@@ -71577,9 +72399,10 @@ function plotBoxMean(sel, axes, trace, t) {
paths.exit().remove();
paths.each(function(d) {
- var posc = posAxis.c2p(d.pos + bPos, true) + bPosPxOffset;
- var pos0 = posAxis.c2p(d.pos + bPos - bdPos0, true) + bPosPxOffset;
- var pos1 = posAxis.c2p(d.pos + bPos + bdPos1, true) + bPosPxOffset;
+ 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);
@@ -71609,7 +72432,7 @@ module.exports = {
plotBoxMean: plotBoxMean
};
-},{"../../components/drawing":72,"../../lib":168,"d3":16}],291:[function(_dereq_,module,exports){
+},{"../../components/drawing":72,"../../lib":169,"d3":16}],294:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -71658,7 +72481,7 @@ module.exports = function selectPoints(searchInfo, selectionTester) {
return selection;
};
-},{}],292:[function(_dereq_,module,exports){
+},{}],295:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -71673,8 +72496,8 @@ var d3 = _dereq_('d3');
var Color = _dereq_('../../components/color');
var Drawing = _dereq_('../../components/drawing');
-function style(gd, cd) {
- var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.boxes');
+function style(gd, cd, sel) {
+ var s = sel ? sel : d3.select(gd).selectAll('g.trace.boxes');
s.style('opacity', function(d) { return d[0].trace.opacity; });
@@ -71716,10 +72539,9 @@ function style(gd, cd) {
});
}
-function styleOnSelect(gd, cd) {
- var s = cd[0].node3;
+function styleOnSelect(gd, cd, sel) {
var trace = cd[0].trace;
- var pts = s.selectAll('path.point');
+ var pts = sel.selectAll('path.point');
if(trace.selectedpoints) {
Drawing.selectedPointStyle(pts, trace);
@@ -71733,7 +72555,7 @@ module.exports = {
styleOnSelect: styleOnSelect
};
-},{"../../components/color":51,"../../components/drawing":72,"d3":16}],293:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../components/drawing":72,"d3":16}],296:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -71755,6 +72577,8 @@ var filterOps = _dereq_('../../constants/filter_ops');
var COMPARISON_OPS2 = filterOps.COMPARISON_OPS2;
var INTERVAL_OPS = filterOps.INTERVAL_OPS;
+var FORMAT_LINK = _dereq_('../../constants/docs').FORMAT_LINK;
+
var scatterLineAttrs = scatterAttrs.line;
module.exports = extendFlat({
@@ -71772,8 +72596,10 @@ module.exports = extendFlat({
ytype: heatmapAttrs.ytype,
zhoverformat: heatmapAttrs.zhoverformat,
hovertemplate: heatmapAttrs.hovertemplate,
-
- connectgaps: heatmapAttrs.connectgaps,
+ hoverongaps: heatmapAttrs.hoverongaps,
+ connectgaps: extendFlat({}, heatmapAttrs.connectgaps, {
+
+ }),
fillcolor: {
valType: 'color',
@@ -71895,9 +72721,13 @@ module.exports = extendFlat({
editType: 'style+colorbars',
}),
- width: extendFlat({}, scatterLineAttrs.width, {
- editType: 'style+colorbars'
- }),
+ width: {
+ valType: 'number',
+ min: 0,
+
+ editType: 'style+colorbars',
+
+ },
dash: dash,
smoothing: extendFlat({}, scatterLineAttrs.smoothing, {
@@ -71912,7 +72742,7 @@ module.exports = extendFlat({
})
);
-},{"../../components/colorscale/attributes":58,"../../components/drawing/attributes":71,"../../constants/filter_ops":147,"../../lib/extend":162,"../../plots/font_attributes":238,"../heatmap/attributes":315,"../scatter/attributes":365}],294:[function(_dereq_,module,exports){
+},{"../../components/colorscale/attributes":58,"../../components/drawing/attributes":71,"../../constants/docs":146,"../../constants/filter_ops":147,"../../lib/extend":164,"../../plots/font_attributes":239,"../heatmap/attributes":318,"../scatter/attributes":377}],297:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -71965,7 +72795,7 @@ module.exports = function calc(gd, trace) {
return cd;
};
-},{"../../components/colorscale":63,"../heatmap/calc":316,"./end_plus":304,"./set_contours":312}],295:[function(_dereq_,module,exports){
+},{"../../components/colorscale":63,"../heatmap/calc":319,"./end_plus":307,"./set_contours":315}],298:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -71976,63 +72806,86 @@ module.exports = function calc(gd, trace) {
'use strict';
-module.exports = function(pathinfo, operation, perimeter, trace) {
- // Abandon all hope, ye who enter here.
- var i, v1, v2;
+module.exports = function(pathinfo, contours) {
var pi0 = pathinfo[0];
- var na = pi0.x.length;
- var nb = pi0.y.length;
var z = pi0.z;
- var contours = trace.contours;
+ var i;
- var boundaryMax = -Infinity;
- var boundaryMin = Infinity;
+ switch(contours.type) {
+ case 'levels':
+ // Why (just) use z[0][0] and z[0][1]?
+ //
+ // N.B. using boundaryMin instead of edgeVal2 here makes the
+ // `contour_scatter` mock fail
+ var edgeVal2 = Math.min(z[0][0], z[0][1]);
- for(i = 0; i < nb; i++) {
- boundaryMin = Math.min(boundaryMin, z[i][0]);
- boundaryMin = Math.min(boundaryMin, z[i][na - 1]);
- boundaryMax = Math.max(boundaryMax, z[i][0]);
- boundaryMax = Math.max(boundaryMax, z[i][na - 1]);
- }
-
- for(i = 1; i < na - 1; i++) {
- boundaryMin = Math.min(boundaryMin, z[0][i]);
- boundaryMin = Math.min(boundaryMin, z[nb - 1][i]);
- boundaryMax = Math.max(boundaryMax, z[0][i]);
- boundaryMax = Math.max(boundaryMax, z[nb - 1][i]);
- }
-
- pi0.prefixBoundary = false;
-
- switch(operation) {
- case '>':
- if(contours.value > boundaryMax) {
- pi0.prefixBoundary = true;
+ for(i = 0; i < pathinfo.length; i++) {
+ var pi = pathinfo[i];
+ pi.prefixBoundary = !pi.edgepaths.length &&
+ (edgeVal2 > pi.level || pi.starts.length && edgeVal2 === pi.level);
}
break;
- case '<':
- if(contours.value < boundaryMin) {
- pi0.prefixBoundary = true;
+ case 'constraint':
+ // after convertToConstraints, pathinfo has length=0
+ pi0.prefixBoundary = false;
+
+ // joinAllPaths does enough already when edgepaths are present
+ if(pi0.edgepaths.length) return;
+
+ var na = pi0.x.length;
+ var nb = pi0.y.length;
+ var boundaryMax = -Infinity;
+ var boundaryMin = Infinity;
+
+ for(i = 0; i < nb; i++) {
+ boundaryMin = Math.min(boundaryMin, z[i][0]);
+ boundaryMin = Math.min(boundaryMin, z[i][na - 1]);
+ boundaryMax = Math.max(boundaryMax, z[i][0]);
+ boundaryMax = Math.max(boundaryMax, z[i][na - 1]);
}
- break;
- case '[]':
- v1 = Math.min.apply(null, contours.value);
- v2 = Math.max.apply(null, contours.value);
- if(v2 < boundaryMin || v1 > boundaryMax) {
- pi0.prefixBoundary = true;
+ for(i = 1; i < na - 1; i++) {
+ boundaryMin = Math.min(boundaryMin, z[0][i]);
+ boundaryMin = Math.min(boundaryMin, z[nb - 1][i]);
+ boundaryMax = Math.max(boundaryMax, z[0][i]);
+ boundaryMax = Math.max(boundaryMax, z[nb - 1][i]);
}
- break;
- case '][':
- v1 = Math.min.apply(null, contours.value);
- v2 = Math.max.apply(null, contours.value);
- if(v1 < boundaryMin && v2 > boundaryMax) {
- pi0.prefixBoundary = true;
+
+ var contoursValue = contours.value;
+ var v1, v2;
+
+ switch(contours._operation) {
+ case '>':
+ if(contoursValue > boundaryMax) {
+ pi0.prefixBoundary = true;
+ }
+ break;
+ case '<':
+ if(contoursValue < boundaryMin ||
+ (pi0.starts.length && contoursValue === boundaryMin)) {
+ pi0.prefixBoundary = true;
+ }
+ break;
+ case '[]':
+ v1 = Math.min(contoursValue[0], contoursValue[1]);
+ v2 = Math.max(contoursValue[0], contoursValue[1]);
+ if(v2 < boundaryMin || v1 > boundaryMax ||
+ (pi0.starts.length && v2 === boundaryMin)) {
+ pi0.prefixBoundary = true;
+ }
+ break;
+ case '][':
+ v1 = Math.min(contoursValue[0], contoursValue[1]);
+ v2 = Math.max(contoursValue[0], contoursValue[1]);
+ if(v1 < boundaryMin && v2 > boundaryMax) {
+ pi0.prefixBoundary = true;
+ }
+ break;
}
break;
}
};
-},{}],296:[function(_dereq_,module,exports){
+},{}],299:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -72081,7 +72934,7 @@ module.exports = {
calc: calc
};
-},{"../../components/colorscale":63,"./end_plus":304,"./make_color_map":309}],297:[function(_dereq_,module,exports){
+},{"../../components/colorscale":63,"./end_plus":307,"./make_color_map":312}],300:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -72159,7 +73012,7 @@ module.exports = {
}
};
-},{}],298:[function(_dereq_,module,exports){
+},{}],301:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -72253,7 +73106,7 @@ function handleConstraintValueDefaults(coerce, contours) {
}
}
-},{"../../components/color":51,"../../constants/filter_ops":147,"./label_defaults":308,"fast-isnumeric":18}],299:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../constants/filter_ops":147,"./label_defaults":311,"fast-isnumeric":18}],302:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -72332,7 +73185,7 @@ function makeInequalitySettings(operation) {
};
}
-},{"../../constants/filter_ops":147,"fast-isnumeric":18}],300:[function(_dereq_,module,exports){
+},{"../../constants/filter_ops":147,"fast-isnumeric":18}],303:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -72361,7 +73214,7 @@ module.exports = function handleContourDefaults(traceIn, traceOut, coerce, coerc
if(autoContour || !contourSize) coerce('ncontours');
};
-},{}],301:[function(_dereq_,module,exports){
+},{}],304:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -72378,6 +73231,8 @@ var Lib = _dereq_('../../lib');
// need weird range loops and flipped contours instead of the usual format. This function
// does some weird manipulation of the extracted pathinfo data such that it magically
// draws contours correctly *as* constraints.
+//
+// ** I do not know which "weird range loops" the comment above is referring to.
module.exports = function(pathinfo, operation) {
var i, pi0, pi1;
@@ -72393,18 +73248,20 @@ module.exports = function(pathinfo, operation) {
Lib.warn('Contour data invalid for the specified inequality operation.');
}
- // In this case there should be exactly two contour levels in pathinfo. We
- // simply concatenate the info into one pathinfo and flip all of the data
- // in one. This will draw the contour as closed.
+ // In this case there should be exactly one contour levels in pathinfo.
+ // We flip all of the data. This will draw the contour as closed.
pi0 = pathinfo[0];
for(i = 0; i < pi0.edgepaths.length; i++) {
pi0.edgepaths[i] = op0(pi0.edgepaths[i]);
}
-
for(i = 0; i < pi0.paths.length; i++) {
pi0.paths[i] = op0(pi0.paths[i]);
}
+ for(i = 0; i < pi0.starts.length; i++) {
+ pi0.starts[i] = op0(pi0.starts[i]);
+ }
+
return pathinfo;
case '][':
var tmp = op0;
@@ -72418,19 +73275,22 @@ module.exports = function(pathinfo, operation) {
Lib.warn('Contour data invalid for the specified inequality range operation.');
}
- // In this case there should be exactly two contour levels in pathinfo. We
- // simply concatenate the info into one pathinfo and flip all of the data
- // in one. This will draw the contour as closed.
+ // In this case there should be exactly two contour levels in pathinfo.
+ // - We concatenate the info into one pathinfo.
+ // - We must also flip all of the data in the `[]` case.
+ // This will draw the contours as closed.
pi0 = copyPathinfo(pathinfo[0]);
pi1 = copyPathinfo(pathinfo[1]);
for(i = 0; i < pi0.edgepaths.length; i++) {
pi0.edgepaths[i] = op0(pi0.edgepaths[i]);
}
-
for(i = 0; i < pi0.paths.length; i++) {
pi0.paths[i] = op0(pi0.paths[i]);
}
+ for(i = 0; i < pi0.starts.length; i++) {
+ pi0.starts[i] = op0(pi0.starts[i]);
+ }
while(pi1.edgepaths.length) {
pi0.edgepaths.push(op1(pi1.edgepaths.shift()));
@@ -72438,6 +73298,10 @@ module.exports = function(pathinfo, operation) {
while(pi1.paths.length) {
pi0.paths.push(op1(pi1.paths.shift()));
}
+ while(pi1.starts.length) {
+ pi0.starts.push(op1(pi1.starts.shift()));
+ }
+
return [pi0];
}
};
@@ -72445,11 +73309,12 @@ module.exports = function(pathinfo, operation) {
function copyPathinfo(pi) {
return Lib.extendFlat({}, pi, {
edgepaths: Lib.extendDeep([], pi.edgepaths),
- paths: Lib.extendDeep([], pi.paths)
+ paths: Lib.extendDeep([], pi.paths),
+ starts: Lib.extendDeep([], pi.starts)
});
}
-},{"../../lib":168}],302:[function(_dereq_,module,exports){
+},{"../../lib":169}],305:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -72487,6 +73352,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerce('text');
coerce('hovertext');
coerce('hovertemplate');
+ coerce('hoverongaps');
var isConstraint = (coerce('contours.type') === 'constraint');
coerce('connectgaps', Lib.isArray1D(traceOut.z));
@@ -72499,7 +73365,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
}
};
-},{"../../lib":168,"../heatmap/xyz_defaults":329,"./attributes":293,"./constraint_defaults":298,"./contours_defaults":300,"./style_defaults":314}],303:[function(_dereq_,module,exports){
+},{"../../lib":169,"../heatmap/xyz_defaults":332,"./attributes":296,"./constraint_defaults":301,"./contours_defaults":303,"./style_defaults":317}],306:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -72563,7 +73429,7 @@ module.exports = function emptyPathinfo(contours, plotinfo, cd0) {
return pathinfo;
};
-},{"../../lib":168,"./constraint_mapping":299,"./end_plus":304}],304:[function(_dereq_,module,exports){
+},{"../../lib":169,"./constraint_mapping":302,"./end_plus":307}],307:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -72583,7 +73449,7 @@ module.exports = function endPlus(contours) {
return contours.end + contours.size / 1e6;
};
-},{}],305:[function(_dereq_,module,exports){
+},{}],308:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -72639,15 +73505,15 @@ function ptDist(pt1, pt2) {
}
function makePath(pi, loc, edgeflag, xtol, ytol) {
- var startLocStr = loc.join(',');
- var locStr = startLocStr;
+ var locStr = loc.join(',');
var mi = pi.crossings[locStr];
- var marchStep = startStep(mi, edgeflag, loc);
+ var marchStep = getStartStep(mi, edgeflag, loc);
// start by going backward a half step and finding the crossing point
var pts = [getInterpPx(pi, loc, [-marchStep[0], -marchStep[1]])];
- var startStepStr = marchStep.join(',');
var m = pi.z.length;
var n = pi.z[0].length;
+ var startLoc = loc.slice();
+ var startStep = marchStep.slice();
var cnt;
// now follow the path
@@ -72669,14 +73535,16 @@ function makePath(pi, loc, edgeflag, xtol, ytol) {
pts.push(getInterpPx(pi, loc, marchStep));
loc[0] += marchStep[0];
loc[1] += marchStep[1];
+ locStr = loc.join(',');
// don't include the same point multiple times
if(equalPts(pts[pts.length - 1], pts[pts.length - 2], xtol, ytol)) pts.pop();
- locStr = loc.join(',');
var atEdge = (marchStep[0] && (loc[0] < 0 || loc[0] > n - 2)) ||
(marchStep[1] && (loc[1] < 0 || loc[1] > m - 2));
- var closedLoop = (locStr === startLocStr) && (marchStep.join(',') === startStepStr);
+
+ var closedLoop = loc[0] === startLoc[0] && loc[1] === startLoc[1] &&
+ marchStep[0] === startStep[0] && marchStep[1] === startStep[1];
// have we completed a loop, or reached an edge?
if((closedLoop) || (edgeflag && atEdge)) break;
@@ -72770,7 +73638,7 @@ function makePath(pi, loc, edgeflag, xtol, ytol) {
} else {
if(!edgeflag) {
Lib.log('Unclosed interior contour?',
- pi.level, startLocStr, pts.join('L'));
+ pi.level, startLoc.join(','), pts.join('L'));
}
// edge path - does it start where an existing edge path ends, or vice versa?
@@ -72820,7 +73688,7 @@ function makePath(pi, loc, edgeflag, xtol, ytol) {
// special function to get the marching step of the
// first point in the path (leading to loc)
-function startStep(mi, edgeflag, loc) {
+function getStartStep(mi, edgeflag, loc) {
var dx = 0;
var dy = 0;
if(mi > 20 && edgeflag) {
@@ -72875,7 +73743,7 @@ function getInterpPx(pi, loc, step) {
}
}
-},{"../../lib":168,"./constants":297}],306:[function(_dereq_,module,exports){
+},{"../../lib":169,"./constants":300}],309:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -72910,7 +73778,7 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLay
return hoverData;
};
-},{"../../components/color":51,"../heatmap/hover":322}],307:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../heatmap/hover":325}],310:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -72939,7 +73807,7 @@ module.exports = {
}
};
-},{"../../plots/cartesian":223,"./attributes":293,"./calc":294,"./colorbar":296,"./defaults":302,"./hover":306,"./plot":311,"./style":313}],308:[function(_dereq_,module,exports){
+},{"../../plots/cartesian":224,"./attributes":296,"./calc":297,"./colorbar":299,"./defaults":305,"./hover":309,"./plot":314,"./style":316}],311:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -72969,7 +73837,7 @@ module.exports = function handleLabelDefaults(coerce, layout, lineColor, opts) {
if(opts.hasHover !== false) coerce('zhoverformat');
};
-},{"../../lib":168}],309:[function(_dereq_,module,exports){
+},{"../../lib":169}],312:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -73053,7 +73921,7 @@ module.exports = function makeColorMap(trace) {
);
};
-},{"../../components/colorscale":63,"./end_plus":304,"d3":16}],310:[function(_dereq_,module,exports){
+},{"../../components/colorscale":63,"./end_plus":307,"d3":16}],313:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -73145,7 +74013,7 @@ function getMarchingIndex(val, corners) {
return (mi === 15) ? 0 : mi;
}
-},{"./constants":297}],311:[function(_dereq_,module,exports){
+},{"./constants":300}],314:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -73161,6 +74029,7 @@ var d3 = _dereq_('d3');
var Lib = _dereq_('../../lib');
var Drawing = _dereq_('../../components/drawing');
+var Colorscale = _dereq_('../../components/colorscale');
var svgTextUtils = _dereq_('../../lib/svg_text_utils');
var Axes = _dereq_('../../plots/cartesian/axes');
var setConvert = _dereq_('../../plots/cartesian/set_convert');
@@ -73211,8 +74080,8 @@ exports.plot = function plot(gd, plotinfo, cdcontours, contourLayer) {
var fillPathinfo = pathinfo;
if(contours.type === 'constraint') {
+ // N.B. this also mutates pathinfo
fillPathinfo = convertToConstraints(pathinfo, contours._operation);
- closeBoundaries(fillPathinfo, contours._operation, perimeter, trace);
}
// draw everything
@@ -73236,10 +74105,17 @@ function makeBackground(plotgroup, perimeter, contours) {
}
function makeFills(plotgroup, pathinfo, perimeter, contours) {
+ var hasFills = contours.coloring === 'fill' || (contours.type === 'constraint' && contours._operation !== '=');
+ var boundaryPath = 'M' + perimeter.join('L') + 'Z';
+
+ // fills prefixBoundary in pathinfo items
+ if(hasFills) {
+ closeBoundaries(pathinfo, contours);
+ }
+
var fillgroup = Lib.ensureSingle(plotgroup, 'g', 'contourfill');
- var fillitems = fillgroup.selectAll('path')
- .data(contours.coloring === 'fill' || (contours.type === 'constraint' && contours._operation !== '=') ? pathinfo : []);
+ var fillitems = fillgroup.selectAll('path').data(hasFills ? pathinfo : []);
fillitems.enter().append('path');
fillitems.exit().remove();
fillitems.each(function(pi) {
@@ -73248,30 +74124,21 @@ function makeFills(plotgroup, pathinfo, perimeter, contours) {
// if the whole perimeter is above this level, start with a path
// enclosing the whole thing. With all that, the parity should mean
// that we always fill everything above the contour, nothing below
- var fullpath = joinAllPaths(pi, perimeter);
+ var fullpath = (pi.prefixBoundary ? boundaryPath : '') +
+ joinAllPaths(pi, perimeter);
- if(!fullpath) d3.select(this).remove();
- else d3.select(this).attr('d', fullpath).style('stroke', 'none');
+ if(!fullpath) {
+ d3.select(this).remove();
+ } else {
+ d3.select(this)
+ .attr('d', fullpath)
+ .style('stroke', 'none');
+ }
});
}
-function initFullPath(pi, perimeter) {
- var prefixBoundary = pi.prefixBoundary;
- if(prefixBoundary === undefined) {
- var edgeVal2 = Math.min(pi.z[0][0], pi.z[0][1]);
- prefixBoundary = (!pi.edgepaths.length && edgeVal2 > pi.level);
- }
-
- if(prefixBoundary) {
- // TODO: why does ^^ not work for constraints?
- // pi.prefixBoundary gets set by closeBoundaries
- return 'M' + perimeter.join('L') + 'Z';
- }
- return '';
-}
-
function joinAllPaths(pi, perimeter) {
- var fullpath = initFullPath(pi, perimeter);
+ var fullpath = '';
var i = 0;
var startsleft = pi.edgepaths.map(function(v, i) { return i; });
var newloop = true;
@@ -73386,7 +74253,7 @@ function makeLinesAndLabels(plotgroup, pathinfo, gd, cd0, contours) {
// invalidate the getTextLocation cache in case paths changed
Lib.clearLocationCache();
- var contourFormat = exports.labelFormatter(contours, cd0.t.cb, gd._fullLayout);
+ var contourFormat = exports.labelFormatter(gd, cd0);
var dummyText = Drawing.tester.append('text')
.attr('data-notex', 1)
@@ -73538,13 +74405,18 @@ exports.createLineClip = function(lineContainer, clipLinesForLabels, gd, uid) {
return lineClip;
};
-exports.labelFormatter = function(contours, colorbar, fullLayout) {
+exports.labelFormatter = function(gd, cd0) {
+ var fullLayout = gd._fullLayout;
+ var trace = cd0.trace;
+ var contours = trace.contours;
+
if(contours.labelformat) {
return fullLayout._d3locale.numberFormat(contours.labelformat);
} else {
var formatAxis;
- if(colorbar) {
- formatAxis = colorbar.axis;
+ var cOpts = Colorscale.extractOpts(trace);
+ if(cOpts && cOpts.colorbar && cOpts.colorbar._axis) {
+ formatAxis = cOpts.colorbar._axis;
} else {
formatAxis = {
type: 'linear',
@@ -73760,17 +74632,18 @@ exports.drawLabels = function(labelGroup, labelData, gd, lineClip, labelClipPath
};
function clipGaps(plotGroup, plotinfo, gd, cd0, perimeter) {
+ var trace = cd0.trace;
var clips = gd._fullLayout._clips;
- var clipId = 'clip' + cd0.trace.uid;
+ var clipId = 'clip' + trace.uid;
var clipPath = clips.selectAll('#' + clipId)
- .data(cd0.trace.connectgaps ? [] : [0]);
+ .data(trace.connectgaps ? [] : [0]);
clipPath.enter().append('clipPath')
.classed('contourclip', true)
.attr('id', clipId);
clipPath.exit().remove();
- if(cd0.trace.connectgaps === false) {
+ if(trace.connectgaps === false) {
var clipPathInfo = {
// fraction of the way from missing to present point
// to draw the boundary.
@@ -73792,10 +74665,13 @@ function clipGaps(plotGroup, plotinfo, gd, cd0, perimeter) {
makeCrossings([clipPathInfo]);
findAllPaths([clipPathInfo]);
- var fullpath = joinAllPaths(clipPathInfo, perimeter);
+ closeBoundaries([clipPathInfo], {type: 'levels'});
var path = Lib.ensureSingle(clipPath, 'path', '');
- path.attr('d', fullpath);
+ path.attr('d',
+ (clipPathInfo.prefixBoundary ? 'M' + perimeter.join('L') + 'Z' : '') +
+ joinAllPaths(clipPathInfo, perimeter)
+ );
} else clipId = null;
Drawing.setClipUrl(plotGroup, clipId, gd);
@@ -73821,7 +74697,7 @@ function makeClipMask(cd0) {
return z;
}
-},{"../../components/drawing":72,"../../lib":168,"../../lib/svg_text_utils":189,"../../plots/cartesian/axes":212,"../../plots/cartesian/set_convert":230,"../heatmap/plot":326,"./close_boundaries":295,"./constants":297,"./convert_to_constraints":301,"./empty_pathinfo":303,"./find_all_paths":305,"./make_crossings":310,"d3":16}],312:[function(_dereq_,module,exports){
+},{"../../components/colorscale":63,"../../components/drawing":72,"../../lib":169,"../../lib/svg_text_utils":190,"../../plots/cartesian/axes":213,"../../plots/cartesian/set_convert":231,"../heatmap/plot":329,"./close_boundaries":298,"./constants":300,"./convert_to_constraints":304,"./empty_pathinfo":306,"./find_all_paths":308,"./make_crossings":313,"d3":16}],315:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -73925,7 +74801,7 @@ function autoContours(start, end, ncontours) {
return dummyAx;
}
-},{"../../lib":168,"../../plots/cartesian/axes":212}],313:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/cartesian/axes":213}],316:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -74006,7 +74882,7 @@ module.exports = function style(gd) {
heatmapStyle(gd);
};
-},{"../../components/drawing":72,"../heatmap/style":327,"./make_color_map":309,"d3":16}],314:[function(_dereq_,module,exports){
+},{"../../components/drawing":72,"../heatmap/style":330,"./make_color_map":312,"d3":16}],317:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -74051,7 +74927,7 @@ module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, layout,
handleLabelDefaults(coerce, layout, lineColor, opts);
};
-},{"../../components/colorscale/defaults":61,"./label_defaults":308}],315:[function(_dereq_,module,exports){
+},{"../../components/colorscale/defaults":61,"./label_defaults":311}],318:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -74063,8 +74939,9 @@ module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, layout,
'use strict';
var scatterAttrs = _dereq_('../scatter/attributes');
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
+var hovertemplateAttrs = _dereq_('../../plots/template_attributes').hovertemplateAttrs;
var colorScaleAttrs = _dereq_('../../components/colorscale/attributes');
+var FORMAT_LINK = _dereq_('../../constants/docs').FORMAT_LINK;
var extendFlat = _dereq_('../../lib/extend').extendFlat;
@@ -74119,10 +74996,16 @@ module.exports = extendFlat({
editType: 'calc',
+ },
+ hoverongaps: {
+ valType: 'boolean',
+ dflt: true,
+
+ editType: 'none',
+
},
connectgaps: {
valType: 'boolean',
- dflt: false,
editType: 'calc',
@@ -74157,7 +75040,7 @@ module.exports = extendFlat({
colorScaleAttrs('', {cLetter: 'z', autoColorDflt: false})
);
-},{"../../components/colorscale/attributes":58,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../scatter/attributes":365}],316:[function(_dereq_,module,exports){
+},{"../../components/colorscale/attributes":58,"../../constants/docs":146,"../../lib/extend":164,"../../plots/template_attributes":253,"../scatter/attributes":377}],319:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -74317,7 +75200,7 @@ module.exports = function calc(gd, trace) {
return [cd0];
};
-},{"../../components/colorscale/calc":59,"../../lib":168,"../../plots/cartesian/axes":212,"../../registry":256,"../histogram2d/calc":344,"./clean_2d_array":317,"./convert_column_xyz":319,"./find_empties":321,"./interp2d":324,"./make_bound_array":325}],317:[function(_dereq_,module,exports){
+},{"../../components/colorscale/calc":59,"../../lib":169,"../../plots/cartesian/axes":213,"../../registry":258,"../histogram2d/calc":347,"./clean_2d_array":320,"./convert_column_xyz":322,"./find_empties":324,"./interp2d":327,"./make_bound_array":328}],320:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -74345,11 +75228,11 @@ module.exports = function clean2dArray(zOld, trace, xa, ya) {
for(i = 0; i < zOld.length; i++) rowlen = Math.max(rowlen, zOld[i].length);
if(rowlen === 0) return false;
getCollen = function(zOld) { return zOld.length; };
- old2new = function(zOld, i, j) { return zOld[j][i]; };
+ old2new = function(zOld, i, j) { return (zOld[j] || [])[i]; };
} else {
rowlen = zOld.length;
getCollen = function(zOld, i) { return zOld[i].length; };
- old2new = function(zOld, i, j) { return zOld[i][j]; };
+ old2new = function(zOld, i, j) { return (zOld[i] || [])[j]; };
}
var padOld2new = function(zOld, i, j) {
@@ -74378,9 +75261,9 @@ module.exports = function clean2dArray(zOld, trace, xa, ya) {
var xMap = axisMapping(xa);
var yMap = axisMapping(ya);
+ if(ya && ya.type === 'category') rowlen = ya._categories.length;
var zNew = new Array(rowlen);
- if(ya && ya.type === 'category') rowlen = ya._categories.length;
for(i = 0; i < rowlen; i++) {
if(xa && xa.type === 'category') {
collen = xa._categories.length;
@@ -74394,7 +75277,7 @@ module.exports = function clean2dArray(zOld, trace, xa, ya) {
return zNew;
};
-},{"../../constants/numerical":149,"../../lib":168,"fast-isnumeric":18}],318:[function(_dereq_,module,exports){
+},{"../../constants/numerical":149,"../../lib":169,"fast-isnumeric":18}],321:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -74410,7 +75293,7 @@ module.exports = {
max: 'zmax'
};
-},{}],319:[function(_dereq_,module,exports){
+},{}],322:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -74488,7 +75371,7 @@ module.exports = function convertColumnData(trace, ax1, ax2, var1Name, var2Name,
}
};
-},{"../../constants/numerical":149,"../../lib":168}],320:[function(_dereq_,module,exports){
+},{"../../constants/numerical":149,"../../lib":169}],323:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -74525,12 +75408,13 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
handleStyleDefaults(traceIn, traceOut, coerce, layout);
+ coerce('hoverongaps');
coerce('connectgaps', Lib.isArray1D(traceOut.z) && (traceOut.zsmooth !== false));
colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'});
};
-},{"../../components/colorscale/defaults":61,"../../lib":168,"./attributes":315,"./style_defaults":328,"./xyz_defaults":329}],321:[function(_dereq_,module,exports){
+},{"../../components/colorscale/defaults":61,"../../lib":169,"./attributes":318,"./style_defaults":331,"./xyz_defaults":332}],324:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -74635,7 +75519,7 @@ module.exports = function findEmpties(z) {
return empties.sort(function(a, b) { return b[2] - a[2]; });
};
-},{"../../lib":168}],322:[function(_dereq_,module,exports){
+},{"../../lib":169}],325:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -74729,6 +75613,8 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLay
var zVal = z[ny][nx];
if(zmask && !zmask[ny][nx]) zVal = undefined;
+ if(zVal === undefined && !trace.hoverongaps) return;
+
var text;
if(Array.isArray(cd0.hovertext) && Array.isArray(cd0.hovertext[ny])) {
text = cd0.hovertext[ny][nx];
@@ -74764,7 +75650,7 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLay
})];
};
-},{"../../components/colorscale":63,"../../components/fx":90,"../../lib":168,"../../plots/cartesian/axes":212}],323:[function(_dereq_,module,exports){
+},{"../../components/colorscale":63,"../../components/fx":89,"../../lib":169,"../../plots/cartesian/axes":213}],326:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -74793,7 +75679,7 @@ module.exports = {
}
};
-},{"../../plots/cartesian":223,"./attributes":315,"./calc":316,"./colorbar":318,"./defaults":320,"./hover":322,"./plot":326,"./style":327}],324:[function(_dereq_,module,exports){
+},{"../../plots/cartesian":224,"./attributes":318,"./calc":319,"./colorbar":321,"./defaults":323,"./hover":325,"./plot":329,"./style":330}],327:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -74926,7 +75812,7 @@ function iterateInterp2d(z, emptyPoints, overshoot) {
return maxFractionalChange;
}
-},{"../../lib":168}],325:[function(_dereq_,module,exports){
+},{"../../lib":169}],328:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -75014,7 +75900,7 @@ module.exports = function makeBoundArray(trace, arrayIn, v0In, dvIn, numbricks,
return arrayOut;
};
-},{"../../lib":168,"../../registry":256}],326:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../registry":258}],329:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -75419,7 +76305,7 @@ function putColor(pixels, pxIndex, c) {
pixels[pxIndex + 3] = Math.round(c[3] * 255);
}
-},{"../../components/colorscale":63,"../../constants/xmlns_namespaces":150,"../../lib":168,"../../registry":256,"d3":16,"tinycolor2":34}],327:[function(_dereq_,module,exports){
+},{"../../components/colorscale":63,"../../constants/xmlns_namespaces":150,"../../lib":169,"../../registry":258,"d3":16,"tinycolor2":34}],330:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -75440,7 +76326,7 @@ module.exports = function style(gd) {
});
};
-},{"d3":16}],328:[function(_dereq_,module,exports){
+},{"d3":16}],331:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -75463,7 +76349,7 @@ module.exports = function handleStyleDefaults(traceIn, traceOut, coerce) {
coerce('zhoverformat');
};
-},{}],329:[function(_dereq_,module,exports){
+},{}],332:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -75560,7 +76446,7 @@ function isValidZ(z) {
return (allRowsAreArrays && oneRowIsFilled && hasOneNumber);
}
-},{"../../lib":168,"../../registry":256,"fast-isnumeric":18}],330:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../registry":258,"fast-isnumeric":18}],333:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -75572,7 +76458,7 @@ function isValidZ(z) {
'use strict';
var barAttrs = _dereq_('../bar/attributes');
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
+var hovertemplateAttrs = _dereq_('../../plots/template_attributes').hovertemplateAttrs;
var makeBinAttrs = _dereq_('./bin_attributes');
var constants = _dereq_('./constants');
var extendFlat = _dereq_('../../lib/extend').extendFlat;
@@ -75701,7 +76587,7 @@ module.exports = {
}
};
-},{"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../bar/attributes":266,"./bin_attributes":332,"./constants":336}],331:[function(_dereq_,module,exports){
+},{"../../lib/extend":164,"../../plots/template_attributes":253,"../bar/attributes":268,"./bin_attributes":335,"./constants":339}],334:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -75726,7 +76612,7 @@ module.exports = function doAvg(size, counts) {
return total;
};
-},{}],332:[function(_dereq_,module,exports){
+},{}],335:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -75761,7 +76647,7 @@ module.exports = function makeBinAttrs(axLetter, match) {
};
};
-},{}],333:[function(_dereq_,module,exports){
+},{}],336:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -75835,7 +76721,7 @@ module.exports = {
}
};
-},{"fast-isnumeric":18}],334:[function(_dereq_,module,exports){
+},{"fast-isnumeric":18}],337:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -76011,7 +76897,7 @@ function dateParts(v, pa, calendar) {
return parts;
}
-},{"../../constants/numerical":149,"../../plots/cartesian/axes":212}],335:[function(_dereq_,module,exports){
+},{"../../constants/numerical":149,"../../plots/cartesian/axes":213}],338:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -76568,7 +77454,7 @@ module.exports = {
calcAllAutoBins: calcAllAutoBins
};
-},{"../../lib":168,"../../plots/cartesian/axes":212,"../../registry":256,"../bar/arrays_to_calcdata":265,"./average":331,"./bin_functions":333,"./bin_label_vals":334,"./norm_functions":342,"fast-isnumeric":18}],336:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/cartesian/axes":213,"../../registry":258,"../bar/arrays_to_calcdata":267,"./average":334,"./bin_functions":336,"./bin_label_vals":337,"./norm_functions":345,"fast-isnumeric":18}],339:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -76584,7 +77470,7 @@ module.exports = {
eventDataKeys: ['binNumber']
};
-},{}],337:[function(_dereq_,module,exports){
+},{}],340:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -76862,7 +77748,7 @@ module.exports = function crossTraceDefaults(fullData, fullLayout) {
}
};
-},{"../../lib":168,"../../plots/cartesian/axis_ids":215,"../../registry":256,"../bar/defaults":270}],338:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/cartesian/axis_ids":216,"../../registry":258,"../bar/defaults":272}],341:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -76936,7 +77822,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
errorBarsSupplyDefaults(traceIn, traceOut, lineColor || Color.defaultLine, {axis: 'x', inherit: 'y'});
};
-},{"../../components/color":51,"../../lib":168,"../../registry":256,"../bar/style_defaults":280,"./attributes":330}],339:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../lib":169,"../../registry":258,"../bar/style_defaults":283,"./attributes":333}],342:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -76985,7 +77871,7 @@ module.exports = function eventData(out, pt, trace, cd, pointNumber) {
return out;
};
-},{}],340:[function(_dereq_,module,exports){
+},{}],343:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77020,7 +77906,7 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
return pts;
};
-},{"../../plots/cartesian/axes":212,"../bar/hover":272}],341:[function(_dereq_,module,exports){
+},{"../../plots/cartesian/axes":213,"../bar/hover":275}],344:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77070,7 +77956,7 @@ module.exports = {
}
};
-},{"../../plots/cartesian":223,"../bar/cross_trace_calc":269,"../bar/layout_attributes":274,"../bar/layout_defaults":275,"../bar/plot":276,"../bar/select":277,"../bar/style":279,"../scatter/marker_colorbar":382,"./attributes":330,"./calc":335,"./cross_trace_defaults":337,"./defaults":338,"./event_data":339,"./hover":340}],342:[function(_dereq_,module,exports){
+},{"../../plots/cartesian":224,"../bar/cross_trace_calc":271,"../bar/layout_attributes":277,"../bar/layout_defaults":278,"../bar/plot":279,"../bar/select":280,"../bar/style":282,"../scatter/marker_colorbar":395,"./attributes":333,"./calc":338,"./cross_trace_defaults":340,"./defaults":341,"./event_data":342,"./hover":343}],345:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77105,7 +77991,7 @@ module.exports = {
}
};
-},{}],343:[function(_dereq_,module,exports){
+},{}],346:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77119,7 +78005,7 @@ module.exports = {
var histogramAttrs = _dereq_('../histogram/attributes');
var makeBinAttrs = _dereq_('../histogram/bin_attributes');
var heatmapAttrs = _dereq_('../heatmap/attributes');
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
+var hovertemplateAttrs = _dereq_('../../plots/template_attributes').hovertemplateAttrs;
var colorScaleAttrs = _dereq_('../../components/colorscale/attributes');
var extendFlat = _dereq_('../../lib/extend').extendFlat;
@@ -77171,7 +78057,7 @@ module.exports = extendFlat(
colorScaleAttrs('', {cLetter: 'z', autoColorDflt: false})
);
-},{"../../components/colorscale/attributes":58,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../heatmap/attributes":315,"../histogram/attributes":330,"../histogram/bin_attributes":332}],344:[function(_dereq_,module,exports){
+},{"../../components/colorscale/attributes":58,"../../lib/extend":164,"../../plots/template_attributes":253,"../heatmap/attributes":318,"../histogram/attributes":333,"../histogram/bin_attributes":335}],347:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77390,7 +78276,7 @@ function getRanges(edges, uniqueVals, gapLow, gapHigh, ax, calendar) {
return out;
}
-},{"../../lib":168,"../../plots/cartesian/axes":212,"../histogram/average":331,"../histogram/bin_functions":333,"../histogram/bin_label_vals":334,"../histogram/calc":335,"../histogram/norm_functions":342}],345:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/cartesian/axes":213,"../histogram/average":334,"../histogram/bin_functions":336,"../histogram/bin_label_vals":337,"../histogram/calc":338,"../histogram/norm_functions":345}],348:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77423,7 +78309,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerce('hovertemplate');
};
-},{"../../components/colorscale/defaults":61,"../../lib":168,"../heatmap/style_defaults":328,"./attributes":343,"./sample_defaults":348}],346:[function(_dereq_,module,exports){
+},{"../../components/colorscale/defaults":61,"../../lib":169,"../heatmap/style_defaults":331,"./attributes":346,"./sample_defaults":351}],349:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77457,7 +78343,7 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLay
return pts;
};
-},{"../../plots/cartesian/axes":212,"../heatmap/hover":322}],347:[function(_dereq_,module,exports){
+},{"../../plots/cartesian/axes":213,"../heatmap/hover":325}],350:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77491,7 +78377,7 @@ module.exports = {
}
};
-},{"../../plots/cartesian":223,"../heatmap/calc":316,"../heatmap/colorbar":318,"../heatmap/plot":326,"../heatmap/style":327,"../histogram/cross_trace_defaults":337,"../histogram/event_data":339,"./attributes":343,"./defaults":345,"./hover":346}],348:[function(_dereq_,module,exports){
+},{"../../plots/cartesian":224,"../heatmap/calc":319,"../heatmap/colorbar":321,"../heatmap/plot":329,"../heatmap/style":330,"../histogram/cross_trace_defaults":340,"../histogram/event_data":342,"./attributes":346,"./defaults":348,"./hover":349}],351:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77536,7 +78422,7 @@ module.exports = function handleSampleDefaults(traceIn, traceOut, coerce, layout
coerce('autobiny');
};
-},{"../../lib":168,"../../registry":256}],349:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../registry":258}],352:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77575,7 +78461,16 @@ module.exports = extendFlat({
autocontour: contourAttrs.autocontour,
ncontours: contourAttrs.ncontours,
contours: contourAttrs.contours,
- line: contourAttrs.line,
+ line: {
+ color: contourAttrs.line.color,
+ width: extendFlat({}, contourAttrs.line.width, {
+ dflt: 0.5,
+
+ }),
+ dash: contourAttrs.line.dash,
+ smoothing: contourAttrs.line.smoothing,
+ editType: 'plot'
+ },
zhoverformat: histogram2dAttrs.zhoverformat,
hovertemplate: histogram2dAttrs.hovertemplate
},
@@ -77585,7 +78480,7 @@ module.exports = extendFlat({
})
);
-},{"../../components/colorscale/attributes":58,"../../lib/extend":162,"../contour/attributes":293,"../histogram2d/attributes":343}],350:[function(_dereq_,module,exports){
+},{"../../components/colorscale/attributes":58,"../../lib/extend":164,"../contour/attributes":296,"../histogram2d/attributes":346}],353:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77622,7 +78517,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerce('hovertemplate');
};
-},{"../../lib":168,"../contour/contours_defaults":300,"../contour/style_defaults":314,"../histogram2d/sample_defaults":348,"./attributes":349}],351:[function(_dereq_,module,exports){
+},{"../../lib":169,"../contour/contours_defaults":303,"../contour/style_defaults":317,"../histogram2d/sample_defaults":351,"./attributes":352}],354:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77654,7 +78549,7 @@ module.exports = {
}
};
-},{"../../plots/cartesian":223,"../contour/calc":294,"../contour/colorbar":296,"../contour/hover":306,"../contour/plot":311,"../contour/style":313,"../histogram/cross_trace_defaults":337,"./attributes":349,"./defaults":350}],352:[function(_dereq_,module,exports){
+},{"../../plots/cartesian":224,"../contour/calc":297,"../contour/colorbar":299,"../contour/hover":309,"../contour/plot":314,"../contour/style":316,"../histogram/cross_trace_defaults":340,"./attributes":352,"./defaults":353}],355:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77665,11 +78560,597 @@ module.exports = {
'use strict';
-var plotAttrs = _dereq_('../../plots/attributes');
+var baseAttrs = _dereq_('../../plots/attributes');
+var hovertemplateAttrs = _dereq_('../../plots/template_attributes').hovertemplateAttrs;
+var extendFlat = _dereq_('../../lib/extend').extendFlat;
+var colormodel = _dereq_('./constants').colormodel;
+
+var cm = ['rgb', 'rgba', 'hsl', 'hsla'];
+var zminDesc = [];
+var zmaxDesc = [];
+for(var i = 0; i < cm.length; i++) {
+ zminDesc.push('For the `' + cm[i] + '` colormodel, it is [' + colormodel[cm[i]].min.join(', ') + '].');
+ zmaxDesc.push('For the `' + cm[i] + '` colormodel, it is [' + colormodel[cm[i]].max.join(', ') + '].');
+}
+
+module.exports = extendFlat({
+ z: {
+ valType: 'data_array',
+
+ editType: 'calc',
+
+ },
+ colormodel: {
+ valType: 'enumerated',
+ values: cm,
+ dflt: 'rgb',
+
+ editType: 'calc',
+
+ },
+ zmin: {
+ valType: 'info_array',
+ items: [
+ {valType: 'number', editType: 'calc'},
+ {valType: 'number', editType: 'calc'},
+ {valType: 'number', editType: 'calc'},
+ {valType: 'number', editType: 'calc'}
+ ],
+
+ editType: 'calc',
+
+ },
+ zmax: {
+ valType: 'info_array',
+ items: [
+ {valType: 'number', editType: 'calc'},
+ {valType: 'number', editType: 'calc'},
+ {valType: 'number', editType: 'calc'},
+ {valType: 'number', editType: 'calc'}
+ ],
+
+ editType: 'calc',
+
+ },
+ x0: {
+ valType: 'any',
+ dflt: 0,
+
+ editType: 'calc+clearAxisTypes',
+
+ },
+ y0: {
+ valType: 'any',
+ dflt: 0,
+
+ editType: 'calc+clearAxisTypes',
+
+ },
+ dx: {
+ valType: 'number',
+ dflt: 1,
+
+ editType: 'calc',
+
+ },
+ dy: {
+ valType: 'number',
+ dflt: 1,
+
+ editType: 'calc',
+
+ },
+ text: {
+ valType: 'data_array',
+ editType: 'plot',
+
+ },
+ hovertext: {
+ valType: 'data_array',
+ editType: 'plot',
+
+ },
+ hoverinfo: extendFlat({}, baseAttrs.hoverinfo, {
+ flags: ['x', 'y', 'z', 'color', 'name', 'text'],
+ dflt: 'x+y+z+text+name'
+ }),
+ hovertemplate: hovertemplateAttrs({}, {
+ keys: ['z', 'color', 'colormodel']
+ }),
+
+ transforms: undefined
+});
+
+},{"../../lib/extend":164,"../../plots/attributes":210,"../../plots/template_attributes":253,"./constants":357}],356:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+var Lib = _dereq_('../../lib');
+var constants = _dereq_('./constants');
+var isNumeric = _dereq_('fast-isnumeric');
+var Axes = _dereq_('../../plots/cartesian/axes');
+var maxRowLength = _dereq_('../../lib').maxRowLength;
+
+module.exports = function calc(gd, trace) {
+ var xa = Axes.getFromId(gd, trace.xaxis || 'x');
+ var ya = Axes.getFromId(gd, trace.yaxis || 'y');
+
+ var x0 = xa.d2c(trace.x0) - trace.dx / 2;
+ var y0 = ya.d2c(trace.y0) - trace.dy / 2;
+ var h = trace.z.length;
+ var w = maxRowLength(trace.z);
+
+ // Set axis range
+ var i;
+ var xrange = [x0, x0 + w * trace.dx];
+ var yrange = [y0, y0 + h * trace.dy];
+ if(xa && xa.type === 'log') for(i = 0; i < w; i++) xrange.push(x0 + i * trace.dx);
+ if(ya && ya.type === 'log') for(i = 0; i < h; i++) yrange.push(y0 + i * trace.dy);
+ trace._extremes[xa._id] = Axes.findExtremes(xa, xrange);
+ trace._extremes[ya._id] = Axes.findExtremes(ya, yrange);
+ trace._scaler = makeScaler(trace);
+
+ var cd0 = {
+ x0: x0,
+ y0: y0,
+ z: trace.z,
+ w: w,
+ h: h
+ };
+ return [cd0];
+};
+
+function scale(zero, ratio, min, max) {
+ return function(c) {
+ return Lib.constrain((c - zero) * ratio, min, max);
+ };
+}
+
+function constrain(min, max) {
+ return function(c) { return Lib.constrain(c, min, max);};
+}
+
+// Generate a function to scale color components according to zmin/zmax and the colormodel
+function makeScaler(trace) {
+ var colormodel = trace.colormodel;
+ var n = colormodel.length;
+ var cr = constants.colormodel[colormodel];
+
+ trace._sArray = [];
+ // Loop over all color components
+ for(var k = 0; k < n; k++) {
+ if(cr.min[k] !== trace.zmin[k] || cr.max[k] !== trace.zmax[k]) {
+ trace._sArray.push(scale(
+ trace.zmin[k],
+ (cr.max[k] - cr.min[k]) / (trace.zmax[k] - trace.zmin[k]),
+ cr.min[k],
+ cr.max[k]
+ ));
+ } else {
+ trace._sArray.push(constrain(cr.min[k], cr.max[k]));
+ }
+ }
+
+ return function(pixel) {
+ var c = pixel.slice(0, n);
+ for(var k = 0; k < n; k++) {
+ var ck = c[k];
+ if(!isNumeric(ck)) return false;
+ c[k] = trace._sArray[k](ck);
+ }
+ return c;
+ };
+}
+
+},{"../../lib":169,"../../plots/cartesian/axes":213,"./constants":357,"fast-isnumeric":18}],357:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+module.exports = {
+ colormodel: {
+ rgb: {
+ min: [0, 0, 0],
+ max: [255, 255, 255],
+ fmt: function(c) {return c.slice(0, 3);},
+ suffix: ['', '', '']
+ },
+ rgba: {
+ min: [0, 0, 0, 0],
+ max: [255, 255, 255, 1],
+ fmt: function(c) {return c.slice(0, 4);},
+ suffix: ['', '', '', '']
+ },
+ hsl: {
+ min: [0, 0, 0],
+ max: [360, 100, 100],
+ fmt: function(c) {
+ var p = c.slice(0, 3);
+ p[1] = p[1] + '%';
+ p[2] = p[2] + '%';
+ return p;
+ },
+ suffix: ['°', '%', '%']
+ },
+ hsla: {
+ min: [0, 0, 0, 0],
+ max: [360, 100, 100, 1],
+ fmt: function(c) {
+ var p = c.slice(0, 4);
+ p[1] = p[1] + '%';
+ p[2] = p[2] + '%';
+ return p;
+ },
+ suffix: ['°', '%', '%', '']
+ }
+ }
+};
+
+},{}],358:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+var Lib = _dereq_('../../lib');
+var attributes = _dereq_('./attributes');
+var constants = _dereq_('./constants');
+
+module.exports = function supplyDefaults(traceIn, traceOut) {
+ function coerce(attr, dflt) {
+ return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
+ }
+ var z = coerce('z');
+ if(z === undefined || !z.length || !z[0] || !z[0].length) {
+ traceOut.visible = false;
+ return;
+ }
+
+ coerce('x0');
+ coerce('y0');
+ coerce('dx');
+ coerce('dy');
+ var colormodel = coerce('colormodel');
+
+ coerce('zmin', constants.colormodel[colormodel].min);
+ coerce('zmax', constants.colormodel[colormodel].max);
+
+ coerce('text');
+ coerce('hovertext');
+ coerce('hovertemplate');
+
+ traceOut._length = null;
+};
+
+},{"../../lib":169,"./attributes":355,"./constants":357}],359:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+module.exports = function eventData(out, pt) {
+ if('xVal' in pt) out.x = pt.xVal;
+ if('yVal' in pt) out.y = pt.yVal;
+ if(pt.xa) out.xaxis = pt.xa;
+ if(pt.ya) out.yaxis = pt.ya;
+ out.color = pt.color;
+ out.colormodel = pt.trace.colormodel;
+ return out;
+};
+
+},{}],360:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+var Fx = _dereq_('../../components/fx');
+var Lib = _dereq_('../../lib');
+var constants = _dereq_('./constants');
+
+module.exports = function hoverPoints(pointData, xval, yval) {
+ var cd0 = pointData.cd[0];
+ var trace = cd0.trace;
+ var xa = pointData.xa;
+ var ya = pointData.ya;
+
+ // Return early if not on image
+ if(Fx.inbox(xval - cd0.x0, xval - (cd0.x0 + cd0.w * trace.dx), 0) > 0 ||
+ Fx.inbox(yval - cd0.y0, yval - (cd0.y0 + cd0.h * trace.dy), 0) > 0) {
+ return;
+ }
+
+ // Find nearest pixel's index
+ var nx = Math.floor((xval - cd0.x0) / trace.dx);
+ var ny = Math.floor(Math.abs(yval - cd0.y0) / trace.dy);
+
+ // return early if pixel is undefined
+ if(!cd0.z[ny][nx]) return;
+
+ var hoverinfo = cd0.hi || trace.hoverinfo;
+ var fmtColor;
+ if(hoverinfo) {
+ var parts = hoverinfo.split('+');
+ if(parts.indexOf('all') !== -1) parts = ['color'];
+ if(parts.indexOf('color') !== -1) fmtColor = true;
+ }
+
+ var colormodel = trace.colormodel;
+ var dims = colormodel.length;
+ var c = trace._scaler(cd0.z[ny][nx]);
+ var s = constants.colormodel[colormodel].suffix;
+
+ var colorstring = [];
+ if(trace.hovertemplate || fmtColor) {
+ colorstring.push('[' + [c[0] + s[0], c[1] + s[1], c[2] + s[2]].join(', '));
+ if(dims === 4) colorstring.push(', ' + c[3] + s[3]);
+ colorstring.push(']');
+ colorstring = colorstring.join('');
+ pointData.extraText = colormodel.toUpperCase() + ': ' + colorstring;
+ }
+
+ var text;
+ if(Array.isArray(trace.hovertext) && Array.isArray(trace.hovertext[ny])) {
+ text = trace.hovertext[ny][nx];
+ } else if(Array.isArray(trace.text) && Array.isArray(trace.text[ny])) {
+ text = trace.text[ny][nx];
+ }
+
+ // TODO: for color model with 3 dims, display something useful for hovertemplate `%{color[3]}`
+ var py = ya.c2p(cd0.y0 + (ny + 0.5) * trace.dy);
+ var xVal = cd0.x0 + (nx + 0.5) * trace.dx;
+ var yVal = cd0.y0 + (ny + 0.5) * trace.dy;
+ var zLabel = '[' + cd0.z[ny][nx].slice(0, trace.colormodel.length).join(', ') + ']';
+ return [Lib.extendFlat(pointData, {
+ index: [ny, nx],
+ x0: xa.c2p(cd0.x0 + nx * trace.dx),
+ x1: xa.c2p(cd0.x0 + (nx + 1) * trace.dx),
+ y0: py,
+ y1: py,
+ color: c,
+ xVal: xVal,
+ xLabelVal: xVal,
+ yVal: yVal,
+ yLabelVal: yVal,
+ zLabelVal: zLabel,
+ text: text,
+ hovertemplateLabels: {
+ 'zLabel': zLabel,
+ 'colorLabel': colorstring,
+ 'color[0]Label': c[0] + s[0],
+ 'color[1]Label': c[1] + s[1],
+ 'color[2]Label': c[2] + s[2],
+ 'color[3]Label': c[3] + s[3]
+ }
+ })];
+};
+
+},{"../../components/fx":89,"../../lib":169,"./constants":357}],361:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+module.exports = {
+ attributes: _dereq_('./attributes'),
+ supplyDefaults: _dereq_('./defaults'),
+ calc: _dereq_('./calc'),
+ plot: _dereq_('./plot'),
+ style: _dereq_('./style'),
+ hoverPoints: _dereq_('./hover'),
+ eventData: _dereq_('./event_data'),
+
+ moduleType: 'trace',
+ name: 'image',
+ basePlotModule: _dereq_('../../plots/cartesian'),
+ categories: ['cartesian', 'svg', '2dMap', 'noSortingByValue'],
+ animatable: false,
+ meta: {
+
+ }
+};
+
+},{"../../plots/cartesian":224,"./attributes":355,"./calc":356,"./defaults":358,"./event_data":359,"./hover":360,"./plot":362,"./style":363}],362:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+var d3 = _dereq_('d3');
+var Lib = _dereq_('../../lib');
+var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces');
+var constants = _dereq_('./constants');
+
+module.exports = function plot(gd, plotinfo, cdimage, imageLayer) {
+ var xa = plotinfo.xaxis;
+ var ya = plotinfo.yaxis;
+
+ Lib.makeTraceGroups(imageLayer, cdimage, 'im').each(function(cd) {
+ var plotGroup = d3.select(this);
+ var cd0 = cd[0];
+ var trace = cd0.trace;
+
+ var z = cd0.z;
+ var x0 = cd0.x0;
+ var y0 = cd0.y0;
+ var w = cd0.w;
+ var h = cd0.h;
+ var dx = trace.dx;
+ var dy = trace.dy;
+
+ var left, right, temp, top, bottom, i;
+ // in case of log of a negative
+ i = 0;
+ while(left === undefined && i < w) {
+ left = xa.c2p(x0 + i * dx);
+ i++;
+ }
+ i = w;
+ while(right === undefined && i > 0) {
+ right = xa.c2p(x0 + i * dx);
+ i--;
+ }
+ i = 0;
+ while(top === undefined && i < h) {
+ top = ya.c2p(y0 + i * dy);
+ i++;
+ }
+ i = h;
+ while(bottom === undefined && i > 0) {
+ bottom = ya.c2p(y0 + i * dy);
+ i--;
+ }
+
+ if(right < left) {
+ temp = right;
+ right = left;
+ left = temp;
+ }
+
+ if(bottom < top) {
+ temp = top;
+ top = bottom;
+ bottom = temp;
+ }
+
+ // Reduce image size when zoomed in to save memory
+ var extra = 0.5; // half the axis size
+ left = Math.max(-extra * xa._length, left);
+ right = Math.min((1 + extra) * xa._length, right);
+ top = Math.max(-extra * ya._length, top);
+ bottom = Math.min((1 + extra) * ya._length, bottom);
+ var imageWidth = Math.round(right - left);
+ var imageHeight = Math.round(bottom - top);
+
+ // if image is entirely off-screen, don't even draw it
+ var isOffScreen = (imageWidth <= 0 || imageHeight <= 0);
+ if(isOffScreen) {
+ var noImage = plotGroup.selectAll('image').data([]);
+ noImage.exit().remove();
+ return;
+ }
+
+ // Draw each pixel
+ var canvas = document.createElement('canvas');
+ canvas.width = imageWidth;
+ canvas.height = imageHeight;
+ var context = canvas.getContext('2d');
+
+ var ipx = function(i) {return Lib.constrain(Math.round(xa.c2p(x0 + i * dx) - left), 0, imageWidth);};
+ var jpx = function(j) {return Lib.constrain(Math.round(ya.c2p(y0 + j * dy) - top), 0, imageHeight);};
+
+ var fmt = constants.colormodel[trace.colormodel].fmt;
+ var c;
+ for(i = 0; i < cd0.w; i++) {
+ var ipx0 = ipx(i); var ipx1 = ipx(i + 1);
+ if(ipx1 === ipx0 || isNaN(ipx1) || isNaN(ipx0)) continue;
+ for(var j = 0; j < cd0.h; j++) {
+ var jpx0 = jpx(j); var jpx1 = jpx(j + 1);
+ if(jpx1 === jpx0 || isNaN(jpx1) || isNaN(jpx0) || !z[j][i]) continue;
+ c = trace._scaler(z[j][i]);
+ if(c) {
+ context.fillStyle = trace.colormodel + '(' + fmt(c).join(',') + ')';
+ } else {
+ // Return a transparent pixel
+ context.fillStyle = 'rgba(0,0,0,0)';
+ }
+ context.fillRect(ipx0, jpx0, ipx1 - ipx0, jpx1 - jpx0);
+ }
+ }
+
+ var image3 = plotGroup.selectAll('image')
+ .data(cd);
+
+ image3.enter().append('svg:image').attr({
+ xmlns: xmlnsNamespaces.svg,
+ preserveAspectRatio: 'none'
+ });
+
+ image3.attr({
+ height: imageHeight,
+ width: imageWidth,
+ x: left,
+ y: top,
+ 'xlink:href': canvas.toDataURL('image/png')
+ });
+ });
+};
+
+},{"../../constants/xmlns_namespaces":150,"../../lib":169,"./constants":357,"d3":16}],363:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+var d3 = _dereq_('d3');
+
+module.exports = function style(gd) {
+ d3.select(gd).selectAll('.im image')
+ .style('opacity', function(d) {
+ return d.trace.opacity;
+ });
+};
+
+},{"d3":16}],364:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+var baseAttrs = _dereq_('../../plots/attributes');
var domainAttrs = _dereq_('../../plots/domain').attributes;
var fontAttrs = _dereq_('../../plots/font_attributes');
var colorAttrs = _dereq_('../../components/color/attributes');
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
+var hovertemplateAttrs = _dereq_('../../plots/template_attributes').hovertemplateAttrs;
+var texttemplateAttrs = _dereq_('../../plots/template_attributes').texttemplateAttrs;
var extendFlat = _dereq_('../../lib/extend').extendFlat;
@@ -77740,7 +79221,7 @@ module.exports = {
text: {
valType: 'data_array',
- editType: 'calc',
+ editType: 'plot',
},
hovertext: {
@@ -77773,12 +79254,15 @@ module.exports = {
editType: 'calc',
},
- hoverinfo: extendFlat({}, plotAttrs.hoverinfo, {
+ hoverinfo: extendFlat({}, baseAttrs.hoverinfo, {
flags: ['label', 'text', 'value', 'percent', 'name']
}),
hovertemplate: hovertemplateAttrs({}, {
keys: ['label', 'color', 'value', 'percent', 'text']
}),
+ texttemplate: texttemplateAttrs({editType: 'plot'}, {
+ keys: ['label', 'color', 'value', 'percent', 'text']
+ }),
textposition: {
valType: 'enumerated',
@@ -77797,6 +79281,13 @@ module.exports = {
outsidetextfont: extendFlat({}, textFontAttrs, {
}),
+ automargin: {
+ valType: 'boolean',
+ dflt: false,
+
+ editType: 'plot',
+
+ },
title: {
text: {
@@ -77906,7 +79397,7 @@ module.exports = {
}
};
-},{"../../components/color/attributes":50,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../../plots/attributes":209,"../../plots/domain":237,"../../plots/font_attributes":238}],353:[function(_dereq_,module,exports){
+},{"../../components/color/attributes":50,"../../lib/extend":164,"../../plots/attributes":210,"../../plots/domain":238,"../../plots/font_attributes":239,"../../plots/template_attributes":253}],365:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77917,27 +79408,19 @@ module.exports = {
'use strict';
-var Registry = _dereq_('../../registry');
-var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData;
+var plots = _dereq_('../../plots/plots');
exports.name = 'pie';
-exports.plot = function(gd) {
- var Pie = Registry.getModule('pie');
- var cdPie = getModuleCalcData(gd.calcdata, Pie)[0];
- Pie.plot(gd, cdPie);
+exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
+ plots.plotBasePlot(exports.name, gd, traces, transitionOpts, makeOnCompleteCallback);
};
exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) {
- var hadPie = (oldFullLayout._has && oldFullLayout._has('pie'));
- var hasPie = (newFullLayout._has && newFullLayout._has('pie'));
-
- if(hadPie && !hasPie) {
- oldFullLayout._pielayer.selectAll('g.trace').remove();
- }
+ plots.cleanBasePlot(exports.name, newFullData, newFullLayout, oldFullData, oldFullLayout);
};
-},{"../../plots/get_data":240,"../../registry":256}],354:[function(_dereq_,module,exports){
+},{"../../plots/plots":245}],366:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -77953,8 +79436,6 @@ var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray;
var tinycolor = _dereq_('tinycolor2');
var Color = _dereq_('../../components/color');
-var helpers = _dereq_('./helpers');
-var isValidTextValue = _dereq_('../../lib').isValidTextValue;
var extendedColorWayList = {};
@@ -78033,32 +79514,6 @@ function calc(gd, trace) {
// include the sum of all values in the first point
if(cd[0]) cd[0].vTotal = vTotal;
- // now insert text
- var textinfo = trace.textinfo;
- if(textinfo && textinfo !== 'none') {
- var parts = textinfo.split('+');
- var hasFlag = function(flag) { return parts.indexOf(flag) !== -1; };
- var hasLabel = hasFlag('label');
- var hasText = hasFlag('text');
- var hasValue = hasFlag('value');
- var hasPercent = hasFlag('percent');
-
- var separators = fullLayout.separators;
- var text;
-
- for(i = 0; i < cd.length; i++) {
- pt = cd[i];
- text = hasLabel ? [pt.label] : [];
- if(hasText) {
- var tx = helpers.getFirstFilled(trace.text, pt.pts);
- if(isValidTextValue(tx)) text.push(tx);
- }
- if(hasValue) text.push(helpers.formatPieValue(pt.v, separators));
- if(hasPercent) text.push(helpers.formatPiePercent(pt.v / vTotal, separators));
- pt.text = text.join('
');
- }
- }
-
return cd;
}
@@ -78149,7 +79604,7 @@ module.exports = {
generateExtendedColors: generateExtendedColors
};
-},{"../../components/color":51,"../../lib":168,"./helpers":357,"fast-isnumeric":18,"tinycolor2":34}],355:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../lib":169,"fast-isnumeric":18,"tinycolor2":34}],367:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -78199,11 +79654,14 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
// TODO: hole needs to be coerced to the same value within a scaleegroup
var textData = coerce('text');
- var textInfo = coerce('textinfo', Array.isArray(textData) ? 'text+percent' : 'percent');
+ var textTemplate = coerce('texttemplate');
+ var textInfo;
+ if(!textTemplate) textInfo = coerce('textinfo', Array.isArray(textData) ? 'text+percent' : 'percent');
+
coerce('hovertext');
coerce('hovertemplate');
- if(textInfo && textInfo !== 'none') {
+ if(textTemplate || (textInfo && textInfo !== 'none')) {
var textposition = coerce('textposition');
handleText(traceIn, traceOut, layout, coerce, textposition, {
moduleHasSelected: false,
@@ -78213,6 +79671,12 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
moduleHasTextangle: false,
moduleHasInsideanchor: false
});
+
+ var hasBoth = Array.isArray(textposition) || textposition === 'auto';
+ var hasOutside = hasBoth || textposition === 'outside';
+ if(hasOutside) {
+ coerce('automargin');
+ }
}
handleDomainDefaults(traceOut, layout, coerce);
@@ -78231,7 +79695,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerce('pull');
};
-},{"../../lib":168,"../../plots/domain":237,"../bar/defaults":270,"./attributes":352}],356:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/domain":238,"../bar/defaults":272,"./attributes":364}],368:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -78280,7 +79744,7 @@ module.exports = function eventData(pt, trace) {
return out;
};
-},{"../../components/fx/helpers":86}],357:[function(_dereq_,module,exports){
+},{"../../components/fx/helpers":86}],369:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -78313,7 +79777,7 @@ exports.getFirstFilled = function getFirstFilled(array, indices) {
if(!Array.isArray(array)) return;
for(var i = 0; i < indices.length; i++) {
var v = array[indices[i]];
- if(v || v === 0) return v;
+ if(v || v === 0 || v === '') return v;
}
};
@@ -78322,7 +79786,7 @@ exports.castOption = function castOption(item, indices) {
else if(item) return item;
};
-},{"../../lib":168}],358:[function(_dereq_,module,exports){
+},{"../../lib":169}],370:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -78355,7 +79819,7 @@ module.exports = {
}
};
-},{"./attributes":352,"./base_plot":353,"./calc":354,"./defaults":355,"./layout_attributes":359,"./layout_defaults":360,"./plot":361,"./style":362,"./style_one":363}],359:[function(_dereq_,module,exports){
+},{"./attributes":364,"./base_plot":365,"./calc":366,"./defaults":367,"./layout_attributes":371,"./layout_defaults":372,"./plot":373,"./style":374,"./style_one":375}],371:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -78388,7 +79852,7 @@ module.exports = {
}
};
-},{}],360:[function(_dereq_,module,exports){
+},{}],372:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -78413,7 +79877,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) {
coerce('extendpiecolors');
};
-},{"../../lib":168,"./layout_attributes":359}],361:[function(_dereq_,module,exports){
+},{"../../lib":169,"./layout_attributes":371}],373:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -78426,6 +79890,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) {
var d3 = _dereq_('d3');
+var Plots = _dereq_('../../plots/plots');
var Fx = _dereq_('../../components/fx');
var Color = _dereq_('../../components/color');
var Drawing = _dereq_('../../components/drawing');
@@ -78434,12 +79899,14 @@ var svgTextUtils = _dereq_('../../lib/svg_text_utils');
var helpers = _dereq_('./helpers');
var eventData = _dereq_('./event_data');
+var isValidTextValue = _dereq_('../../lib').isValidTextValue;
function plot(gd, cdModule) {
var fullLayout = gd._fullLayout;
+ var gs = fullLayout._size;
prerenderTitles(cdModule, gd);
- layoutAreas(cdModule, fullLayout._size);
+ layoutAreas(cdModule, gs);
var plotGroups = Lib.makeTraceGroups(fullLayout._pielayer, cdModule, 'trace').each(function(cd) {
var plotGroup = d3.select(this);
@@ -78541,6 +80008,7 @@ function plot(gd, cdModule) {
}
// add text
+ formatSliceLabel(gd, pt, cd0);
var textPosition = helpers.castOption(trace.textposition, pt.pts);
var sliceTextGroup = sliceTop.selectAll('g.slicetext')
.data(pt.text && (textPosition !== 'none') ? [0] : []);
@@ -78642,7 +80110,7 @@ function plot(gd, cdModule) {
if(trace.title.position === 'middle center') {
transform = positionTitleInside(cd0);
} else {
- transform = positionTitleOutside(cd0, fullLayout._size);
+ transform = positionTitleOutside(cd0, gs);
}
titleText.attr('transform',
@@ -78655,6 +80123,31 @@ function plot(gd, cdModule) {
if(hasOutsideText) scootLabels(quadrants, trace);
plotTextLines(slices, trace);
+
+ if(hasOutsideText && trace.automargin) {
+ // TODO if we ever want to improve perf,
+ // we could reuse the textBB computed above together
+ // with the sliceText transform info
+ var traceBbox = Drawing.bBox(plotGroup.node());
+
+ var domain = trace.domain;
+ var vpw = gs.w * (domain.x[1] - domain.x[0]);
+ var vph = gs.h * (domain.y[1] - domain.y[0]);
+ var xgap = (0.5 * vpw - cd0.r) / gs.w;
+ var ygap = (0.5 * vph - cd0.r) / gs.h;
+
+ Plots.autoMargin(gd, 'pie.' + trace.uid + '.automargin', {
+ xl: domain.x[0] - xgap,
+ xr: domain.x[1] + xgap,
+ yb: domain.y[0] - ygap,
+ yt: domain.y[1] + ygap,
+ l: Math.max(cd0.cx - cd0.r - traceBbox.left, 0),
+ r: Math.max(traceBbox.right - (cd0.cx + cd0.r), 0),
+ b: Math.max(traceBbox.bottom - (cd0.cy + cd0.r), 0),
+ t: Math.max(cd0.cy - cd0.r - traceBbox.top, 0),
+ pad: 5
+ });
+ }
});
});
@@ -79357,8 +80850,63 @@ function setCoords(cd) {
}
}
+function formatSliceLabel(gd, pt, cd0) {
+ var fullLayout = gd._fullLayout;
+ var trace = cd0.trace;
+ // look for textemplate
+ var texttemplate = trace.texttemplate;
+
+ // now insert text
+ var textinfo = trace.textinfo;
+ if(!texttemplate && textinfo && textinfo !== 'none') {
+ var parts = textinfo.split('+');
+ var hasFlag = function(flag) { return parts.indexOf(flag) !== -1; };
+ var hasLabel = hasFlag('label');
+ var hasText = hasFlag('text');
+ var hasValue = hasFlag('value');
+ var hasPercent = hasFlag('percent');
+
+ var separators = fullLayout.separators;
+ var text;
+
+ text = hasLabel ? [pt.label] : [];
+ if(hasText) {
+ var tx = helpers.getFirstFilled(trace.text, pt.pts);
+ if(isValidTextValue(tx)) text.push(tx);
+ }
+ if(hasValue) text.push(helpers.formatPieValue(pt.v, separators));
+ if(hasPercent) text.push(helpers.formatPiePercent(pt.v / cd0.vTotal, separators));
+ pt.text = text.join('
');
+ }
+
+ function makeTemplateVariables(pt) {
+ return {
+ label: pt.label,
+ value: pt.v,
+ valueLabel: helpers.formatPieValue(pt.v, fullLayout.separators),
+ percent: pt.v / cd0.vTotal,
+ percentLabel: helpers.formatPiePercent(pt.v / cd0.vTotal, fullLayout.separators),
+ color: pt.color,
+ text: pt.text,
+ customdata: Lib.castOption(trace, pt.i, 'customdata')
+ };
+ }
+
+ if(texttemplate) {
+ var txt = Lib.castOption(trace, pt.i, 'texttemplate');
+ if(!txt) {
+ pt.text = '';
+ } else {
+ var obj = makeTemplateVariables(pt);
+ var ptTx = helpers.getFirstFilled(trace.text, pt.pts);
+ if(isValidTextValue(ptTx) || ptTx === '') obj.text = ptTx;
+ pt.text = Lib.texttemplateString(txt, obj, gd._fullLayout._d3locale, obj, trace._meta || {});
+ }
+ }
+}
module.exports = {
plot: plot,
+ formatSliceLabel: formatSliceLabel,
transformInsideText: transformInsideText,
determineInsideTextFont: determineInsideTextFont,
positionTitleOutside: positionTitleOutside,
@@ -79367,7 +80915,7 @@ module.exports = {
attachFxHandlers: attachFxHandlers,
};
-},{"../../components/color":51,"../../components/drawing":72,"../../components/fx":90,"../../lib":168,"../../lib/svg_text_utils":189,"./event_data":356,"./helpers":357,"d3":16}],362:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../components/drawing":72,"../../components/fx":89,"../../lib":169,"../../lib/svg_text_utils":190,"../../plots/plots":245,"./event_data":368,"./helpers":369,"d3":16}],374:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -79396,7 +80944,7 @@ module.exports = function style(gd) {
});
};
-},{"./style_one":363,"d3":16}],363:[function(_dereq_,module,exports){
+},{"./style_one":375,"d3":16}],375:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -79420,7 +80968,7 @@ module.exports = function styleOne(s, pt, trace) {
.call(Color.stroke, lineColor);
};
-},{"../../components/color":51,"./helpers":357}],364:[function(_dereq_,module,exports){
+},{"../../components/color":51,"./helpers":369}],376:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -79441,26 +80989,27 @@ module.exports = function arraysToCalcdata(cd, trace) {
for(var i = 0; i < cd.length; i++) cd[i].i = i;
Lib.mergeArray(trace.text, cd, 'tx');
+ Lib.mergeArray(trace.texttemplate, cd, 'txt');
Lib.mergeArray(trace.hovertext, cd, 'htx');
Lib.mergeArray(trace.customdata, cd, 'data');
Lib.mergeArray(trace.textposition, cd, 'tp');
if(trace.textfont) {
- Lib.mergeArray(trace.textfont.size, cd, 'ts');
+ Lib.mergeArrayCastPositive(trace.textfont.size, cd, 'ts');
Lib.mergeArray(trace.textfont.color, cd, 'tc');
Lib.mergeArray(trace.textfont.family, cd, 'tf');
}
var marker = trace.marker;
if(marker) {
- Lib.mergeArray(marker.size, cd, 'ms');
- Lib.mergeArray(marker.opacity, cd, 'mo');
+ Lib.mergeArrayCastPositive(marker.size, cd, 'ms');
+ Lib.mergeArrayCastPositive(marker.opacity, cd, 'mo');
Lib.mergeArray(marker.symbol, cd, 'mx');
Lib.mergeArray(marker.color, cd, 'mc');
var markerLine = marker.line;
if(marker.line) {
Lib.mergeArray(markerLine.color, cd, 'mlc');
- Lib.mergeArray(markerLine.width, cd, 'mlw');
+ Lib.mergeArrayCastPositive(markerLine.width, cd, 'mlw');
}
var markerGradient = marker.gradient;
@@ -79471,7 +81020,7 @@ module.exports = function arraysToCalcdata(cd, trace) {
}
};
-},{"../../lib":168}],365:[function(_dereq_,module,exports){
+},{"../../lib":169}],377:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -79482,7 +81031,8 @@ module.exports = function arraysToCalcdata(cd, trace) {
'use strict';
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
+var texttemplateAttrs = _dereq_('../../plots/template_attributes').texttemplateAttrs;
+var hovertemplateAttrs = _dereq_('../../plots/template_attributes').hovertemplateAttrs;
var colorScaleAttrs = _dereq_('../../components/colorscale/attributes');
var fontAttrs = _dereq_('../../plots/font_attributes');
var dash = _dereq_('../../components/drawing/attributes').dash;
@@ -79576,6 +81126,10 @@ module.exports = {
editType: 'calc',
},
+
+ texttemplate: texttemplateAttrs({}, {
+
+ }),
hovertext: {
valType: 'string',
@@ -79880,7 +81434,7 @@ module.exports = {
}
};
-},{"../../components/colorscale/attributes":58,"../../components/drawing":72,"../../components/drawing/attributes":71,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../../plots/font_attributes":238,"./constants":369}],366:[function(_dereq_,module,exports){
+},{"../../components/colorscale/attributes":58,"../../components/drawing":72,"../../components/drawing/attributes":71,"../../lib/extend":164,"../../plots/font_attributes":239,"../../plots/template_attributes":253,"./constants":381}],378:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -80165,7 +81719,7 @@ module.exports = {
getStackOpts: getStackOpts
};
-},{"../../constants/numerical":149,"../../lib":168,"../../plots/cartesian/axes":212,"./arrays_to_calcdata":364,"./calc_selection":367,"./colorscale_calc":368,"./subtypes":388,"fast-isnumeric":18}],367:[function(_dereq_,module,exports){
+},{"../../constants/numerical":149,"../../lib":169,"../../plots/cartesian/axes":213,"./arrays_to_calcdata":376,"./calc_selection":379,"./colorscale_calc":380,"./subtypes":401,"fast-isnumeric":18}],379:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -80184,7 +81738,7 @@ module.exports = function calcSelection(cd, trace) {
}
};
-},{"../../lib":168}],368:[function(_dereq_,module,exports){
+},{"../../lib":169}],380:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -80227,7 +81781,7 @@ module.exports = function calcMarkerColorscale(gd, trace) {
}
};
-},{"../../components/colorscale/calc":59,"../../components/colorscale/helpers":62,"./subtypes":388}],369:[function(_dereq_,module,exports){
+},{"../../components/colorscale/calc":59,"../../components/colorscale/helpers":62,"./subtypes":401}],381:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -80256,7 +81810,7 @@ module.exports = {
eventDataKeys: []
};
-},{}],370:[function(_dereq_,module,exports){
+},{}],382:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -80437,7 +81991,7 @@ function getInterp(calcTrace, index, position, posAttr) {
return pt0.s + (pt1.s - pt0.s) * (position - pt0[posAttr]) / (pt1[posAttr] - pt0[posAttr]);
}
-},{"./calc":366}],371:[function(_dereq_,module,exports){
+},{"./calc":378}],383:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -80476,7 +82030,7 @@ module.exports = function crossTraceDefaults(fullData) {
}
};
-},{}],372:[function(_dereq_,module,exports){
+},{}],384:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -80531,6 +82085,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
}
if(subTypes.hasText(traceOut)) {
+ coerce('texttemplate');
handleTextDefaults(traceIn, traceOut, layout, coerce);
}
@@ -80565,7 +82120,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
Lib.coerceSelectionMarkerOpacity(traceOut, coerce);
};
-},{"../../lib":168,"../../registry":256,"./attributes":365,"./constants":369,"./fillcolor_defaults":373,"./line_defaults":377,"./line_shape_defaults":379,"./marker_defaults":383,"./stack_defaults":386,"./subtypes":388,"./text_defaults":389,"./xy_defaults":390}],373:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../registry":258,"./attributes":377,"./constants":381,"./fillcolor_defaults":385,"./line_defaults":390,"./line_shape_defaults":392,"./marker_defaults":396,"./stack_defaults":399,"./subtypes":401,"./text_defaults":402,"./xy_defaults":403}],385:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -80602,7 +82157,33 @@ module.exports = function fillColorDefaults(traceIn, traceOut, defaultColor, coe
));
};
-},{"../../components/color":51,"../../lib":168}],374:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../lib":169}],386:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
+
+'use strict';
+
+var Axes = _dereq_('../../plots/cartesian/axes');
+
+module.exports = function formatLabels(cdi, trace, fullLayout) {
+ var labels = {};
+
+ var mockGd = {_fullLayout: fullLayout};
+ var xa = Axes.getFromTrace(mockGd, trace, 'x');
+ var ya = Axes.getFromTrace(mockGd, trace, 'y');
+
+ labels.xLabel = Axes.tickText(xa, cdi.x, true).text;
+ labels.yLabel = Axes.tickText(ya, cdi.y, true).text;
+
+ return labels;
+};
+
+},{"../../plots/cartesian/axes":213}],387:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -80651,7 +82232,7 @@ module.exports = function getTraceColor(trace, di) {
}
};
-},{"../../components/color":51,"./subtypes":388}],375:[function(_dereq_,module,exports){
+},{"../../components/color":51,"./subtypes":401}],388:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -80846,7 +82427,7 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
}
};
-},{"../../components/color":51,"../../components/fx":90,"../../lib":168,"../../registry":256,"./get_trace_color":374}],376:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../components/fx":89,"../../lib":169,"../../registry":258,"./get_trace_color":387}],389:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -80873,6 +82454,7 @@ module.exports = {
arraysToCalcdata: _dereq_('./arrays_to_calcdata'),
plot: _dereq_('./plot'),
colorbar: _dereq_('./marker_colorbar'),
+ formatLabels: _dereq_('./format_labels'),
style: _dereq_('./style').style,
styleOnSelect: _dereq_('./style').styleOnSelect,
hoverPoints: _dereq_('./hover'),
@@ -80891,7 +82473,7 @@ module.exports = {
}
};
-},{"../../plots/cartesian":223,"./arrays_to_calcdata":364,"./attributes":365,"./calc":366,"./cross_trace_calc":370,"./cross_trace_defaults":371,"./defaults":372,"./hover":375,"./marker_colorbar":382,"./plot":384,"./select":385,"./style":387,"./subtypes":388}],377:[function(_dereq_,module,exports){
+},{"../../plots/cartesian":224,"./arrays_to_calcdata":376,"./attributes":377,"./calc":378,"./cross_trace_calc":382,"./cross_trace_defaults":383,"./defaults":384,"./format_labels":386,"./hover":388,"./marker_colorbar":395,"./plot":397,"./select":398,"./style":400,"./subtypes":401}],390:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -80922,7 +82504,7 @@ module.exports = function lineDefaults(traceIn, traceOut, defaultColor, layout,
if(!(opts || {}).noDash) coerce('line.dash');
};
-},{"../../components/colorscale/defaults":61,"../../components/colorscale/helpers":62,"../../lib":168}],378:[function(_dereq_,module,exports){
+},{"../../components/colorscale/defaults":61,"../../components/colorscale/helpers":62,"../../lib":169}],391:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -80992,8 +82574,8 @@ module.exports = function linePoints(d, opts) {
function getPt(index) {
var di = d[index];
if(!di) return false;
- var x = xa.c2p(di.x);
- var y = ya.c2p(di.y);
+ var x = opts.linearized ? xa.l2p(di.x) : xa.c2p(di.x);
+ var y = opts.linearized ? ya.l2p(di.y) : ya.c2p(di.y);
// if non-positive log values, set them VERY far off-screen
// so the line looks essentially straight from the previous point.
@@ -81383,7 +82965,7 @@ module.exports = function linePoints(d, opts) {
return segments;
};
-},{"../../constants/numerical":149,"../../lib":168,"./constants":369}],379:[function(_dereq_,module,exports){
+},{"../../constants/numerical":149,"../../lib":169,"./constants":381}],392:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -81402,7 +82984,7 @@ module.exports = function handleLineShapeDefaults(traceIn, traceOut, coerce) {
if(shape === 'spline') coerce('line.smoothing');
};
-},{}],380:[function(_dereq_,module,exports){
+},{}],393:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -81492,7 +83074,7 @@ module.exports = function linkTraces(gd, plotinfo, cdscatter) {
return cdscatterSorted;
};
-},{}],381:[function(_dereq_,module,exports){
+},{}],394:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -81534,7 +83116,7 @@ module.exports = function makeBubbleSizeFn(trace) {
};
};
-},{"fast-isnumeric":18}],382:[function(_dereq_,module,exports){
+},{"fast-isnumeric":18}],395:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -81552,7 +83134,7 @@ module.exports = {
max: 'cmax'
};
-},{}],383:[function(_dereq_,module,exports){
+},{}],396:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -81633,7 +83215,7 @@ module.exports = function markerDefaults(traceIn, traceOut, defaultColor, layout
}
};
-},{"../../components/color":51,"../../components/colorscale/defaults":61,"../../components/colorscale/helpers":62,"./subtypes":388}],384:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../components/colorscale/defaults":61,"../../components/colorscale/helpers":62,"./subtypes":401}],397:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -81788,7 +83370,7 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
if(ownFillDir !== 'x' && ownFillDir !== 'y') ownFillDir = '';
// store node for tweaking by selectPoints
- if(!plotinfo.isRangePlot) cdscatter[0].node3 = tr;
+ cdscatter[0][plotinfo.isRangePlot ? 'nodeRangePlot3' : 'node3'] = tr;
var prevRevpath = '';
var prevPolygons = [];
@@ -82194,7 +83776,7 @@ function selectMarkers(gd, idx, plotinfo, cdscatter, cdscatterAll) {
});
}
-},{"../../components/drawing":72,"../../lib":168,"../../lib/polygon":180,"../../registry":256,"./line_points":378,"./link_traces":380,"./subtypes":388,"d3":16}],385:[function(_dereq_,module,exports){
+},{"../../components/drawing":72,"../../lib":169,"../../lib/polygon":181,"../../registry":258,"./line_points":391,"./link_traces":393,"./subtypes":401,"d3":16}],398:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -82248,7 +83830,7 @@ module.exports = function selectPoints(searchInfo, selectionTester) {
return selection;
};
-},{"./subtypes":388}],386:[function(_dereq_,module,exports){
+},{"./subtypes":401}],399:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -82353,7 +83935,7 @@ module.exports = function handleStackDefaults(traceIn, traceOut, layout, coerce)
}
};
-},{}],387:[function(_dereq_,module,exports){
+},{}],400:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -82369,8 +83951,8 @@ var d3 = _dereq_('d3');
var Drawing = _dereq_('../../components/drawing');
var Registry = _dereq_('../../registry');
-function style(gd, cd) {
- var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.scatter');
+function style(gd) {
+ var s = d3.select(gd).selectAll('g.trace.scatter');
s.style('opacity', function(d) {
return d[0].trace.opacity;
@@ -82405,16 +83987,15 @@ function styleText(sel, trace, gd) {
Drawing.textPointStyle(sel.selectAll('text'), trace, gd);
}
-function styleOnSelect(gd, cd) {
- var s = cd[0].node3;
+function styleOnSelect(gd, cd, sel) {
var trace = cd[0].trace;
if(trace.selectedpoints) {
- Drawing.selectedPointStyle(s.selectAll('path.point'), trace);
- Drawing.selectedTextStyle(s.selectAll('text'), trace);
+ Drawing.selectedPointStyle(sel.selectAll('path.point'), trace);
+ Drawing.selectedTextStyle(sel.selectAll('text'), trace);
} else {
- stylePoints(s, trace, gd);
- styleText(s, trace, gd);
+ stylePoints(sel, trace, gd);
+ styleText(sel, trace, gd);
}
}
@@ -82425,7 +84006,7 @@ module.exports = {
styleOnSelect: styleOnSelect
};
-},{"../../components/drawing":72,"../../registry":256,"d3":16}],388:[function(_dereq_,module,exports){
+},{"../../components/drawing":72,"../../registry":258,"d3":16}],401:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -82464,7 +84045,7 @@ module.exports = {
}
};
-},{"../../lib":168}],389:[function(_dereq_,module,exports){
+},{"../../lib":169}],402:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -82494,7 +84075,7 @@ module.exports = function(traceIn, traceOut, layout, coerce, opts) {
}
};
-},{"../../lib":168}],390:[function(_dereq_,module,exports){
+},{"../../lib":169}],403:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -82538,7 +84119,7 @@ module.exports = function handleXYDefaults(traceIn, traceOut, layout, coerce) {
return len;
};
-},{"../../lib":168,"../../registry":256}],391:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../registry":258}],404:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -82549,9 +84130,10 @@ module.exports = function handleXYDefaults(traceIn, traceOut, layout, coerce) {
'use strict';
-var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes');
+var hovertemplateAttrs = _dereq_('../../plots/template_attributes').hovertemplateAttrs;
+var texttemplateAttrs = _dereq_('../../plots/template_attributes').texttemplateAttrs;
var scatterAttrs = _dereq_('../scatter/attributes');
-var plotAttrs = _dereq_('../../plots/attributes');
+var baseAttrs = _dereq_('../../plots/attributes');
var colorScaleAttrs = _dereq_('../../components/colorscale/attributes');
var dash = _dereq_('../../components/drawing/attributes').dash;
@@ -82588,6 +84170,9 @@ module.exports = {
mode: extendFlat({}, scatterAttrs.mode, {dflt: 'markers'}),
text: extendFlat({}, scatterAttrs.text, {
+ }),
+ texttemplate: texttemplateAttrs({editType: 'plot'}, {
+ keys: ['a', 'b', 'c', 'text']
}),
hovertext: extendFlat({}, scatterAttrs.hovertext, {
@@ -82635,14 +84220,14 @@ module.exports = {
selected: scatterAttrs.selected,
unselected: scatterAttrs.unselected,
- hoverinfo: extendFlat({}, plotAttrs.hoverinfo, {
+ hoverinfo: extendFlat({}, baseAttrs.hoverinfo, {
flags: ['a', 'b', 'c', 'text', 'name']
}),
hoveron: scatterAttrs.hoveron,
hovertemplate: hovertemplateAttrs(),
};
-},{"../../components/colorscale/attributes":58,"../../components/drawing/attributes":71,"../../components/fx/hovertemplate_attributes":89,"../../lib/extend":162,"../../plots/attributes":209,"../scatter/attributes":365}],392:[function(_dereq_,module,exports){
+},{"../../components/colorscale/attributes":58,"../../components/drawing/attributes":71,"../../lib/extend":164,"../../plots/attributes":210,"../../plots/template_attributes":253,"../scatter/attributes":377}],405:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -82723,7 +84308,7 @@ module.exports = function calc(gd, trace) {
return cd;
};
-},{"../scatter/arrays_to_calcdata":364,"../scatter/calc":366,"../scatter/calc_selection":367,"../scatter/colorscale_calc":368,"fast-isnumeric":18}],393:[function(_dereq_,module,exports){
+},{"../scatter/arrays_to_calcdata":376,"../scatter/calc":378,"../scatter/calc_selection":379,"../scatter/colorscale_calc":380,"fast-isnumeric":18}],406:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -82801,6 +84386,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
}
if(subTypes.hasText(traceOut)) {
+ coerce('texttemplate');
handleTextDefaults(traceIn, traceOut, layout, coerce);
}
@@ -82826,7 +84412,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
Lib.coerceSelectionMarkerOpacity(traceOut, coerce);
};
-},{"../../lib":168,"../scatter/constants":369,"../scatter/fillcolor_defaults":373,"../scatter/line_defaults":377,"../scatter/line_shape_defaults":379,"../scatter/marker_defaults":383,"../scatter/subtypes":388,"../scatter/text_defaults":389,"./attributes":391}],394:[function(_dereq_,module,exports){
+},{"../../lib":169,"../scatter/constants":381,"../scatter/fillcolor_defaults":385,"../scatter/line_defaults":390,"../scatter/line_shape_defaults":392,"../scatter/marker_defaults":396,"../scatter/subtypes":401,"../scatter/text_defaults":402,"./attributes":404}],407:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -82858,7 +84444,7 @@ module.exports = function eventData(out, pt, trace, cd, pointNumber) {
return out;
};
-},{}],395:[function(_dereq_,module,exports){
+},{}],408:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -82867,12 +84453,33 @@ module.exports = function eventData(out, pt, trace, cd, pointNumber) {
* LICENSE file in the root directory of this source tree.
*/
+'use strict';
+
+var Axes = _dereq_('../../plots/cartesian/axes');
+
+module.exports = function formatLabels(cdi, trace, fullLayout) {
+ var labels = {};
+
+ var subplot = fullLayout[trace.subplot]._subplot;
+ labels.aLabel = Axes.tickText(subplot.aaxis, cdi.a, true).text;
+ labels.bLabel = Axes.tickText(subplot.baxis, cdi.b, true).text;
+ labels.cLabel = Axes.tickText(subplot.caxis, cdi.c, true).text;
+
+ return labels;
+};
+
+},{"../../plots/cartesian/axes":213}],409:[function(_dereq_,module,exports){
+/**
+* Copyright 2012-2019, 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.
+*/
'use strict';
var scatterHover = _dereq_('../scatter/hover');
-var Axes = _dereq_('../../plots/cartesian/axes');
-
module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
var scatterPointData = scatterHover(pointData, xval, yval, hovermode);
@@ -82901,6 +84508,8 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
}
var cdi = newPointData.cd[newPointData.index];
+ var trace = newPointData.trace;
+ var subplot = newPointData.subplot;
newPointData.a = cdi.a;
newPointData.b = cdi.b;
@@ -82908,28 +84517,32 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
newPointData.xLabelVal = undefined;
newPointData.yLabelVal = undefined;
- // TODO: nice formatting, and label by axis title, for a, b, and c?
- var trace = newPointData.trace;
- var ternary = newPointData.subplot;
+ var fullLayout = {};
+ fullLayout[trace.subplot] = {_subplot: subplot};
+ var labels = trace._module.formatLabels(cdi, trace, fullLayout);
+ newPointData.aLabel = labels.aLabel;
+ newPointData.bLabel = labels.bLabel;
+ newPointData.cLabel = labels.cLabel;
+
var hoverinfo = cdi.hi || trace.hoverinfo;
var text = [];
function textPart(ax, val) {
- text.push(ax._hovertitle + ': ' + Axes.tickText(ax, val, 'hover').text);
+ text.push(ax._hovertitle + ': ' + val);
}
if(!trace.hovertemplate) {
var parts = hoverinfo.split('+');
if(parts.indexOf('all') !== -1) parts = ['a', 'b', 'c'];
- if(parts.indexOf('a') !== -1) textPart(ternary.aaxis, cdi.a);
- if(parts.indexOf('b') !== -1) textPart(ternary.baxis, cdi.b);
- if(parts.indexOf('c') !== -1) textPart(ternary.caxis, cdi.c);
+ if(parts.indexOf('a') !== -1) textPart(subplot.aaxis, newPointData.aLabel);
+ if(parts.indexOf('b') !== -1) textPart(subplot.baxis, newPointData.bLabel);
+ if(parts.indexOf('c') !== -1) textPart(subplot.caxis, newPointData.cLabel);
}
newPointData.extraText = text.join('
');
newPointData.hovertemplate = trace.hovertemplate;
return scatterPointData;
};
-},{"../../plots/cartesian/axes":212,"../scatter/hover":375}],396:[function(_dereq_,module,exports){
+},{"../scatter/hover":388}],410:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -82944,6 +84557,7 @@ module.exports = {
attributes: _dereq_('./attributes'),
supplyDefaults: _dereq_('./defaults'),
colorbar: _dereq_('../scatter/marker_colorbar'),
+ formatLabels: _dereq_('./format_labels'),
calc: _dereq_('./calc'),
plot: _dereq_('./plot'),
style: _dereq_('../scatter/style').style,
@@ -82962,7 +84576,7 @@ module.exports = {
}
};
-},{"../../plots/ternary":252,"../scatter/marker_colorbar":382,"../scatter/select":385,"../scatter/style":387,"./attributes":391,"./calc":392,"./defaults":393,"./event_data":394,"./hover":395,"./plot":397}],397:[function(_dereq_,module,exports){
+},{"../../plots/ternary":254,"../scatter/marker_colorbar":395,"../scatter/select":398,"../scatter/style":400,"./attributes":404,"./calc":405,"./defaults":406,"./event_data":407,"./format_labels":408,"./hover":409,"./plot":411}],411:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -82995,7 +84609,7 @@ module.exports = function plot(gd, ternary, moduleCalcData) {
scatterPlot(gd, plotinfo, moduleCalcData, scatterLayer);
};
-},{"../scatter/plot":384}],398:[function(_dereq_,module,exports){
+},{"../scatter/plot":397}],412:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -83194,7 +84808,7 @@ module.exports = {
}
};
-},{"../../lib/extend":162,"../box/attributes":281}],399:[function(_dereq_,module,exports){
+},{"../../lib/extend":164,"../box/attributes":284}],413:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -83370,7 +84984,7 @@ function calcSpan(trace, cdi, valAxis, bandwidth) {
return spanOut;
}
-},{"../../constants/numerical":149,"../../lib":168,"../../plots/cartesian/axes":212,"../box/calc":282,"./helpers":402}],400:[function(_dereq_,module,exports){
+},{"../../constants/numerical":149,"../../lib":169,"../../plots/cartesian/axes":213,"../box/calc":285,"./helpers":416}],414:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -83413,7 +85027,7 @@ module.exports = function crossTraceCalc(gd, plotinfo) {
}
};
-},{"../box/cross_trace_calc":283}],401:[function(_dereq_,module,exports){
+},{"../box/cross_trace_calc":286}],415:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -83474,7 +85088,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
if(!meanLineVisible) traceOut.meanline = {visible: false};
};
-},{"../../components/color":51,"../../lib":168,"../box/defaults":284,"./attributes":398}],402:[function(_dereq_,module,exports){
+},{"../../components/color":51,"../../lib":169,"../box/defaults":287,"./attributes":412}],416:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -83547,7 +85161,7 @@ exports.getKdeValue = function(calcItem, trace, valueDist) {
exports.extractVal = function(o) { return o.v; };
-},{"../../lib":168}],403:[function(_dereq_,module,exports){
+},{"../../lib":169}],417:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -83659,7 +85273,7 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLay
return closeData;
};
-},{"../../lib":168,"../../plots/cartesian/axes":212,"../box/hover":286,"./helpers":402}],404:[function(_dereq_,module,exports){
+},{"../../lib":169,"../../plots/cartesian/axes":213,"../box/hover":289,"./helpers":416}],418:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -83693,7 +85307,7 @@ module.exports = {
}
};
-},{"../../plots/cartesian":223,"../box/defaults":284,"../box/select":291,"../scatter/style":387,"./attributes":398,"./calc":399,"./cross_trace_calc":400,"./defaults":401,"./hover":403,"./layout_attributes":405,"./layout_defaults":406,"./plot":407,"./style":408}],405:[function(_dereq_,module,exports){
+},{"../../plots/cartesian":224,"../box/defaults":287,"../box/select":294,"../scatter/style":400,"./attributes":412,"./calc":413,"./cross_trace_calc":414,"./defaults":415,"./hover":417,"./layout_attributes":419,"./layout_defaults":420,"./plot":421,"./style":422}],419:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -83719,7 +85333,7 @@ module.exports = {
})
};
-},{"../../lib":168,"../box/layout_attributes":288}],406:[function(_dereq_,module,exports){
+},{"../../lib":169,"../box/layout_attributes":291}],420:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -83741,7 +85355,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
boxLayoutDefaults._supply(layoutIn, layoutOut, fullData, coerce, 'violin');
};
-},{"../../lib":168,"../box/layout_defaults":289,"./layout_attributes":405}],407:[function(_dereq_,module,exports){
+},{"../../lib":169,"../box/layout_defaults":292,"./layout_attributes":419}],421:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -83772,7 +85386,8 @@ module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) {
connectGaps: true,
baseTolerance: 0.75,
shape: 'spline',
- simplify: true
+ simplify: true,
+ linearized: true
});
return Drawing.smoothopen(segments[0], 1);
}
@@ -83782,7 +85397,6 @@ module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) {
var cd0 = cd[0];
var t = cd0.t;
var trace = cd0.trace;
- if(!plotinfo.isRangePlot) cd0.node3 = plotGroup;
if(trace.visible !== true || t.empty) {
plotGroup.remove();
@@ -83809,8 +85423,8 @@ module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) {
var pathSel = d3.select(this);
var density = d.density;
var len = density.length;
- var posCenter = d.pos + bPos;
- var posCenterPx = posAxis.c2p(posCenter);
+ var posCenter = posAxis.c2l(d.pos + bPos, true);
+ var posCenterPx = posAxis.l2p(posCenter);
var scale;
if(trace.width) {
@@ -83830,7 +85444,7 @@ module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) {
for(i = 0; i < len; i++) {
pt = pts[i] = {};
pt[t.posLetter] = posCenter + (density[i].v / scale);
- pt[t.valLetter] = density[i].t;
+ pt[t.valLetter] = valAxis.c2l(density[i].t, true);
}
pathPos = makePath(pts);
}
@@ -83840,7 +85454,7 @@ module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) {
for(k = 0, i = len - 1; k < len; k++, i--) {
pt = pts[k] = {};
pt[t.posLetter] = posCenter - (density[i].v / scale);
- pt[t.valLetter] = density[i].t;
+ pt[t.valLetter] = valAxis.c2l(density[i].t, true);
}
pathNeg = makePath(pts);
}
@@ -83883,10 +85497,10 @@ module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) {
bPosPxOffset = 0;
} else if(hasPositiveSide) {
bdPosScaled = [0, bdPos * boxWidth / 2];
- bPosPxOffset = -boxLineWidth;
+ bPosPxOffset = boxLineWidth * {x: 1, y: -1}[t.posLetter];
} else {
bdPosScaled = [bdPos * boxWidth / 2, 0];
- bPosPxOffset = boxLineWidth;
+ bPosPxOffset = boxLineWidth * {x: -1, y: 1}[t.posLetter];
}
// inner box
@@ -83931,7 +85545,7 @@ module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) {
});
};
-},{"../../components/drawing":72,"../../lib":168,"../box/plot":290,"../scatter/line_points":378,"./helpers":402,"d3":16}],408:[function(_dereq_,module,exports){
+},{"../../components/drawing":72,"../../lib":169,"../box/plot":293,"../scatter/line_points":391,"./helpers":416,"d3":16}],422:[function(_dereq_,module,exports){
/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
@@ -83946,8 +85560,8 @@ var d3 = _dereq_('d3');
var Color = _dereq_('../../components/color');
var stylePoints = _dereq_('../scatter/style').stylePoints;
-module.exports = function style(gd, cd) {
- var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.violins');
+module.exports = function style(gd) {
+ var s = d3.select(gd).selectAll('g.trace.violins');
s.style('opacity', function(d) { return d[0].trace.opacity; });
@@ -83986,5 +85600,5 @@ module.exports = function style(gd, cd) {
});
};
-},{"../../components/color":51,"../scatter/style":387,"d3":16}]},{},[11])(11)
+},{"../../components/color":51,"../scatter/style":400,"d3":16}]},{},[11])(11)
});
diff --git a/static/babybuddy/js/graph.js.gz b/static/babybuddy/js/graph.js.gz
index f7fa75b6..9da51fa4 100644
Binary files a/static/babybuddy/js/graph.js.gz and b/static/babybuddy/js/graph.js.gz differ
diff --git a/static/babybuddy/js/vendor.3aed05379df2.js b/static/babybuddy/js/vendor.3aed05379df2.js
deleted file mode 100644
index 7bec0dc7..00000000
--- a/static/babybuddy/js/vendor.3aed05379df2.js
+++ /dev/null
@@ -1,25030 +0,0 @@
-/*!
- * jQuery JavaScript Library v3.4.1
- * https://jquery.com/
- *
- * Includes Sizzle.js
- * https://sizzlejs.com/
- *
- * Copyright JS Foundation and other contributors
- * Released under the MIT license
- * https://jquery.org/license
- *
- * Date: 2019-05-01T21:04Z
- */
-( function( global, factory ) {
-
- "use strict";
-
- if ( typeof module === "object" && typeof module.exports === "object" ) {
-
- // For CommonJS and CommonJS-like environments where a proper `window`
- // is present, execute the factory and get jQuery.
- // For environments that do not have a `window` with a `document`
- // (such as Node.js), expose a factory as module.exports.
- // This accentuates the need for the creation of a real `window`.
- // e.g. var jQuery = require("jquery")(window);
- // See ticket #14549 for more info.
- module.exports = global.document ?
- factory( global, true ) :
- function( w ) {
- if ( !w.document ) {
- throw new Error( "jQuery requires a window with a document" );
- }
- return factory( w );
- };
- } else {
- factory( global );
- }
-
-// Pass this if window is not defined yet
-} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
-
-// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
-// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
-// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
-// enough that all such attempts are guarded in a try block.
-"use strict";
-
-var arr = [];
-
-var document = window.document;
-
-var getProto = Object.getPrototypeOf;
-
-var slice = arr.slice;
-
-var concat = arr.concat;
-
-var push = arr.push;
-
-var indexOf = arr.indexOf;
-
-var class2type = {};
-
-var toString = class2type.toString;
-
-var hasOwn = class2type.hasOwnProperty;
-
-var fnToString = hasOwn.toString;
-
-var ObjectFunctionString = fnToString.call( Object );
-
-var support = {};
-
-var isFunction = function isFunction( obj ) {
-
- // Support: Chrome <=57, Firefox <=52
- // In some browsers, typeof returns "function" for HTML
elements
- // (i.e., `typeof document.createElement( "object" ) === "function"`).
- // We don't want to classify *any* DOM node as a function.
- return typeof obj === "function" && typeof obj.nodeType !== "number";
- };
-
-
-var isWindow = function isWindow( obj ) {
- return obj != null && obj === obj.window;
- };
-
-
-
-
- var preservedScriptAttributes = {
- type: true,
- src: true,
- nonce: true,
- noModule: true
- };
-
- function DOMEval( code, node, doc ) {
- doc = doc || document;
-
- var i, val,
- script = doc.createElement( "script" );
-
- script.text = code;
- if ( node ) {
- for ( i in preservedScriptAttributes ) {
-
- // Support: Firefox 64+, Edge 18+
- // Some browsers don't support the "nonce" property on scripts.
- // On the other hand, just using `getAttribute` is not enough as
- // the `nonce` attribute is reset to an empty string whenever it
- // becomes browsing-context connected.
- // See https://github.com/whatwg/html/issues/2369
- // See https://html.spec.whatwg.org/#nonce-attributes
- // The `node.getAttribute` check was added for the sake of
- // `jQuery.globalEval` so that it can fake a nonce-containing node
- // via an object.
- val = node[ i ] || node.getAttribute && node.getAttribute( i );
- if ( val ) {
- script.setAttribute( i, val );
- }
- }
- }
- doc.head.appendChild( script ).parentNode.removeChild( script );
- }
-
-
-function toType( obj ) {
- if ( obj == null ) {
- return obj + "";
- }
-
- // Support: Android <=2.3 only (functionish RegExp)
- return typeof obj === "object" || typeof obj === "function" ?
- class2type[ toString.call( obj ) ] || "object" :
- typeof obj;
-}
-/* global Symbol */
-// Defining this global in .eslintrc.json would create a danger of using the global
-// unguarded in another place, it seems safer to define global only for this module
-
-
-
-var
- version = "3.4.1",
-
- // Define a local copy of jQuery
- jQuery = function( selector, context ) {
-
- // The jQuery object is actually just the init constructor 'enhanced'
- // Need init if jQuery is called (just allow error to be thrown if not included)
- return new jQuery.fn.init( selector, context );
- },
-
- // Support: Android <=4.0 only
- // Make sure we trim BOM and NBSP
- rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
-
-jQuery.fn = jQuery.prototype = {
-
- // The current version of jQuery being used
- jquery: version,
-
- constructor: jQuery,
-
- // The default length of a jQuery object is 0
- length: 0,
-
- toArray: function() {
- return slice.call( this );
- },
-
- // Get the Nth element in the matched element set OR
- // Get the whole matched element set as a clean array
- get: function( num ) {
-
- // Return all the elements in a clean array
- if ( num == null ) {
- return slice.call( this );
- }
-
- // Return just the one element from the set
- return num < 0 ? this[ num + this.length ] : this[ num ];
- },
-
- // Take an array of elements and push it onto the stack
- // (returning the new matched element set)
- pushStack: function( elems ) {
-
- // Build a new jQuery matched element set
- var ret = jQuery.merge( this.constructor(), elems );
-
- // Add the old object onto the stack (as a reference)
- ret.prevObject = this;
-
- // Return the newly-formed element set
- return ret;
- },
-
- // Execute a callback for every element in the matched set.
- each: function( callback ) {
- return jQuery.each( this, callback );
- },
-
- map: function( callback ) {
- return this.pushStack( jQuery.map( this, function( elem, i ) {
- return callback.call( elem, i, elem );
- } ) );
- },
-
- slice: function() {
- return this.pushStack( slice.apply( this, arguments ) );
- },
-
- first: function() {
- return this.eq( 0 );
- },
-
- last: function() {
- return this.eq( -1 );
- },
-
- eq: function( i ) {
- var len = this.length,
- j = +i + ( i < 0 ? len : 0 );
- return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
- },
-
- end: function() {
- return this.prevObject || this.constructor();
- },
-
- // For internal use only.
- // Behaves like an Array's method, not like a jQuery method.
- push: push,
- sort: arr.sort,
- splice: arr.splice
-};
-
-jQuery.extend = jQuery.fn.extend = function() {
- var options, name, src, copy, copyIsArray, clone,
- target = arguments[ 0 ] || {},
- i = 1,
- length = arguments.length,
- deep = false;
-
- // Handle a deep copy situation
- if ( typeof target === "boolean" ) {
- deep = target;
-
- // Skip the boolean and the target
- target = arguments[ i ] || {};
- i++;
- }
-
- // Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !isFunction( target ) ) {
- target = {};
- }
-
- // Extend jQuery itself if only one argument is passed
- if ( i === length ) {
- target = this;
- i--;
- }
-
- for ( ; i < length; i++ ) {
-
- // Only deal with non-null/undefined values
- if ( ( options = arguments[ i ] ) != null ) {
-
- // Extend the base object
- for ( name in options ) {
- copy = options[ name ];
-
- // Prevent Object.prototype pollution
- // Prevent never-ending loop
- if ( name === "__proto__" || target === copy ) {
- continue;
- }
-
- // Recurse if we're merging plain objects or arrays
- if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
- ( copyIsArray = Array.isArray( copy ) ) ) ) {
- src = target[ name ];
-
- // Ensure proper type for the source value
- if ( copyIsArray && !Array.isArray( src ) ) {
- clone = [];
- } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
- clone = {};
- } else {
- clone = src;
- }
- copyIsArray = false;
-
- // Never move original objects, clone them
- target[ name ] = jQuery.extend( deep, clone, copy );
-
- // Don't bring in undefined values
- } else if ( copy !== undefined ) {
- target[ name ] = copy;
- }
- }
- }
- }
-
- // Return the modified object
- return target;
-};
-
-jQuery.extend( {
-
- // Unique for each copy of jQuery on the page
- expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
-
- // Assume jQuery is ready without the ready module
- isReady: true,
-
- error: function( msg ) {
- throw new Error( msg );
- },
-
- noop: function() {},
-
- isPlainObject: function( obj ) {
- var proto, Ctor;
-
- // Detect obvious negatives
- // Use toString instead of jQuery.type to catch host objects
- if ( !obj || toString.call( obj ) !== "[object Object]" ) {
- return false;
- }
-
- proto = getProto( obj );
-
- // Objects with no prototype (e.g., `Object.create( null )`) are plain
- if ( !proto ) {
- return true;
- }
-
- // Objects with prototype are plain iff they were constructed by a global Object function
- Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
- return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
- },
-
- isEmptyObject: function( obj ) {
- var name;
-
- for ( name in obj ) {
- return false;
- }
- return true;
- },
-
- // Evaluates a script in a global context
- globalEval: function( code, options ) {
- DOMEval( code, { nonce: options && options.nonce } );
- },
-
- each: function( obj, callback ) {
- var length, i = 0;
-
- if ( isArrayLike( obj ) ) {
- length = obj.length;
- for ( ; i < length; i++ ) {
- if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
- break;
- }
- }
- } else {
- for ( i in obj ) {
- if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
- break;
- }
- }
- }
-
- return obj;
- },
-
- // Support: Android <=4.0 only
- trim: function( text ) {
- return text == null ?
- "" :
- ( text + "" ).replace( rtrim, "" );
- },
-
- // results is for internal usage only
- makeArray: function( arr, results ) {
- var ret = results || [];
-
- if ( arr != null ) {
- if ( isArrayLike( Object( arr ) ) ) {
- jQuery.merge( ret,
- typeof arr === "string" ?
- [ arr ] : arr
- );
- } else {
- push.call( ret, arr );
- }
- }
-
- return ret;
- },
-
- inArray: function( elem, arr, i ) {
- return arr == null ? -1 : indexOf.call( arr, elem, i );
- },
-
- // Support: Android <=4.0 only, PhantomJS 1 only
- // push.apply(_, arraylike) throws on ancient WebKit
- merge: function( first, second ) {
- var len = +second.length,
- j = 0,
- i = first.length;
-
- for ( ; j < len; j++ ) {
- first[ i++ ] = second[ j ];
- }
-
- first.length = i;
-
- return first;
- },
-
- grep: function( elems, callback, invert ) {
- var callbackInverse,
- matches = [],
- i = 0,
- length = elems.length,
- callbackExpect = !invert;
-
- // Go through the array, only saving the items
- // that pass the validator function
- for ( ; i < length; i++ ) {
- callbackInverse = !callback( elems[ i ], i );
- if ( callbackInverse !== callbackExpect ) {
- matches.push( elems[ i ] );
- }
- }
-
- return matches;
- },
-
- // arg is for internal usage only
- map: function( elems, callback, arg ) {
- var length, value,
- i = 0,
- ret = [];
-
- // Go through the array, translating each of the items to their new values
- if ( isArrayLike( elems ) ) {
- length = elems.length;
- for ( ; i < length; i++ ) {
- value = callback( elems[ i ], i, arg );
-
- if ( value != null ) {
- ret.push( value );
- }
- }
-
- // Go through every key on the object,
- } else {
- for ( i in elems ) {
- value = callback( elems[ i ], i, arg );
-
- if ( value != null ) {
- ret.push( value );
- }
- }
- }
-
- // Flatten any nested arrays
- return concat.apply( [], ret );
- },
-
- // A global GUID counter for objects
- guid: 1,
-
- // jQuery.support is not used in Core but other projects attach their
- // properties to it so it needs to exist.
- support: support
-} );
-
-if ( typeof Symbol === "function" ) {
- jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
-}
-
-// Populate the class2type map
-jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
-function( i, name ) {
- class2type[ "[object " + name + "]" ] = name.toLowerCase();
-} );
-
-function isArrayLike( obj ) {
-
- // Support: real iOS 8.2 only (not reproducible in simulator)
- // `in` check used to prevent JIT error (gh-2145)
- // hasOwn isn't used here due to false negatives
- // regarding Nodelist length in IE
- var length = !!obj && "length" in obj && obj.length,
- type = toType( obj );
-
- if ( isFunction( obj ) || isWindow( obj ) ) {
- return false;
- }
-
- return type === "array" || length === 0 ||
- typeof length === "number" && length > 0 && ( length - 1 ) in obj;
-}
-var Sizzle =
-/*!
- * Sizzle CSS Selector Engine v2.3.4
- * https://sizzlejs.com/
- *
- * Copyright JS Foundation and other contributors
- * Released under the MIT license
- * https://js.foundation/
- *
- * Date: 2019-04-08
- */
-(function( window ) {
-
-var i,
- support,
- Expr,
- getText,
- isXML,
- tokenize,
- compile,
- select,
- outermostContext,
- sortInput,
- hasDuplicate,
-
- // Local document vars
- setDocument,
- document,
- docElem,
- documentIsHTML,
- rbuggyQSA,
- rbuggyMatches,
- matches,
- contains,
-
- // Instance-specific data
- expando = "sizzle" + 1 * new Date(),
- preferredDoc = window.document,
- dirruns = 0,
- done = 0,
- classCache = createCache(),
- tokenCache = createCache(),
- compilerCache = createCache(),
- nonnativeSelectorCache = createCache(),
- sortOrder = function( a, b ) {
- if ( a === b ) {
- hasDuplicate = true;
- }
- return 0;
- },
-
- // Instance methods
- hasOwn = ({}).hasOwnProperty,
- arr = [],
- pop = arr.pop,
- push_native = arr.push,
- push = arr.push,
- slice = arr.slice,
- // Use a stripped-down indexOf as it's faster than native
- // https://jsperf.com/thor-indexof-vs-for/5
- indexOf = function( list, elem ) {
- var i = 0,
- len = list.length;
- for ( ; i < len; i++ ) {
- if ( list[i] === elem ) {
- return i;
- }
- }
- return -1;
- },
-
- booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
-
- // Regular expressions
-
- // http://www.w3.org/TR/css3-selectors/#whitespace
- whitespace = "[\\x20\\t\\r\\n\\f]",
-
- // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
- identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
-
- // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
- attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
- // Operator (capture 2)
- "*([*^$|!~]?=)" + whitespace +
- // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
- "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
- "*\\]",
-
- pseudos = ":(" + identifier + ")(?:\\((" +
- // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
- // 1. quoted (capture 3; capture 4 or capture 5)
- "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
- // 2. simple (capture 6)
- "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
- // 3. anything else (capture 2)
- ".*" +
- ")\\)|)",
-
- // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
- rwhitespace = new RegExp( whitespace + "+", "g" ),
- rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
-
- rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
- rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
- rdescend = new RegExp( whitespace + "|>" ),
-
- rpseudo = new RegExp( pseudos ),
- ridentifier = new RegExp( "^" + identifier + "$" ),
-
- matchExpr = {
- "ID": new RegExp( "^#(" + identifier + ")" ),
- "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
- "TAG": new RegExp( "^(" + identifier + "|[*])" ),
- "ATTR": new RegExp( "^" + attributes ),
- "PSEUDO": new RegExp( "^" + pseudos ),
- "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
- "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
- "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
- "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
- // For use in libraries implementing .is()
- // We use this for POS matching in `select`
- "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
- whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
- },
-
- rhtml = /HTML$/i,
- rinputs = /^(?:input|select|textarea|button)$/i,
- rheader = /^h\d$/i,
-
- rnative = /^[^{]+\{\s*\[native \w/,
-
- // Easily-parseable/retrievable ID or TAG or CLASS selectors
- rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
-
- rsibling = /[+~]/,
-
- // CSS escapes
- // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
- runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
- funescape = function( _, escaped, escapedWhitespace ) {
- var high = "0x" + escaped - 0x10000;
- // NaN means non-codepoint
- // Support: Firefox<24
- // Workaround erroneous numeric interpretation of +"0x"
- return high !== high || escapedWhitespace ?
- escaped :
- high < 0 ?
- // BMP codepoint
- String.fromCharCode( high + 0x10000 ) :
- // Supplemental Plane codepoint (surrogate pair)
- String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
- },
-
- // CSS string/identifier serialization
- // https://drafts.csswg.org/cssom/#common-serializing-idioms
- rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
- fcssescape = function( ch, asCodePoint ) {
- if ( asCodePoint ) {
-
- // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
- if ( ch === "\0" ) {
- return "\uFFFD";
- }
-
- // Control characters and (dependent upon position) numbers get escaped as code points
- return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
- }
-
- // Other potentially-special ASCII characters get backslash-escaped
- return "\\" + ch;
- },
-
- // Used for iframes
- // See setDocument()
- // Removing the function wrapper causes a "Permission Denied"
- // error in IE
- unloadHandler = function() {
- setDocument();
- },
-
- inDisabledFieldset = addCombinator(
- function( elem ) {
- return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset";
- },
- { dir: "parentNode", next: "legend" }
- );
-
-// Optimize for push.apply( _, NodeList )
-try {
- push.apply(
- (arr = slice.call( preferredDoc.childNodes )),
- preferredDoc.childNodes
- );
- // Support: Android<4.0
- // Detect silently failing push.apply
- arr[ preferredDoc.childNodes.length ].nodeType;
-} catch ( e ) {
- push = { apply: arr.length ?
-
- // Leverage slice if possible
- function( target, els ) {
- push_native.apply( target, slice.call(els) );
- } :
-
- // Support: IE<9
- // Otherwise append directly
- function( target, els ) {
- var j = target.length,
- i = 0;
- // Can't trust NodeList.length
- while ( (target[j++] = els[i++]) ) {}
- target.length = j - 1;
- }
- };
-}
-
-function Sizzle( selector, context, results, seed ) {
- var m, i, elem, nid, match, groups, newSelector,
- newContext = context && context.ownerDocument,
-
- // nodeType defaults to 9, since context defaults to document
- nodeType = context ? context.nodeType : 9;
-
- results = results || [];
-
- // Return early from calls with invalid selector or context
- if ( typeof selector !== "string" || !selector ||
- nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
-
- return results;
- }
-
- // Try to shortcut find operations (as opposed to filters) in HTML documents
- if ( !seed ) {
-
- if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
- setDocument( context );
- }
- context = context || document;
-
- if ( documentIsHTML ) {
-
- // If the selector is sufficiently simple, try using a "get*By*" DOM method
- // (excepting DocumentFragment context, where the methods don't exist)
- if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
-
- // ID selector
- if ( (m = match[1]) ) {
-
- // Document context
- if ( nodeType === 9 ) {
- if ( (elem = context.getElementById( m )) ) {
-
- // Support: IE, Opera, Webkit
- // TODO: identify versions
- // getElementById can match elements by name instead of ID
- if ( elem.id === m ) {
- results.push( elem );
- return results;
- }
- } else {
- return results;
- }
-
- // Element context
- } else {
-
- // Support: IE, Opera, Webkit
- // TODO: identify versions
- // getElementById can match elements by name instead of ID
- if ( newContext && (elem = newContext.getElementById( m )) &&
- contains( context, elem ) &&
- elem.id === m ) {
-
- results.push( elem );
- return results;
- }
- }
-
- // Type selector
- } else if ( match[2] ) {
- push.apply( results, context.getElementsByTagName( selector ) );
- return results;
-
- // Class selector
- } else if ( (m = match[3]) && support.getElementsByClassName &&
- context.getElementsByClassName ) {
-
- push.apply( results, context.getElementsByClassName( m ) );
- return results;
- }
- }
-
- // Take advantage of querySelectorAll
- if ( support.qsa &&
- !nonnativeSelectorCache[ selector + " " ] &&
- (!rbuggyQSA || !rbuggyQSA.test( selector )) &&
-
- // Support: IE 8 only
- // Exclude object elements
- (nodeType !== 1 || context.nodeName.toLowerCase() !== "object") ) {
-
- newSelector = selector;
- newContext = context;
-
- // qSA considers elements outside a scoping root when evaluating child or
- // descendant combinators, which is not what we want.
- // In such cases, we work around the behavior by prefixing every selector in the
- // list with an ID selector referencing the scope context.
- // Thanks to Andrew Dupont for this technique.
- if ( nodeType === 1 && rdescend.test( selector ) ) {
-
- // Capture the context ID, setting it first if necessary
- if ( (nid = context.getAttribute( "id" )) ) {
- nid = nid.replace( rcssescape, fcssescape );
- } else {
- context.setAttribute( "id", (nid = expando) );
- }
-
- // Prefix every selector in the list
- groups = tokenize( selector );
- i = groups.length;
- while ( i-- ) {
- groups[i] = "#" + nid + " " + toSelector( groups[i] );
- }
- newSelector = groups.join( "," );
-
- // Expand context for sibling selectors
- newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
- context;
- }
-
- try {
- push.apply( results,
- newContext.querySelectorAll( newSelector )
- );
- return results;
- } catch ( qsaError ) {
- nonnativeSelectorCache( selector, true );
- } finally {
- if ( nid === expando ) {
- context.removeAttribute( "id" );
- }
- }
- }
- }
- }
-
- // All others
- return select( selector.replace( rtrim, "$1" ), context, results, seed );
-}
-
-/**
- * Create key-value caches of limited size
- * @returns {function(string, object)} Returns the Object data after storing it on itself with
- * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
- * deleting the oldest entry
- */
-function createCache() {
- var keys = [];
-
- function cache( key, value ) {
- // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
- if ( keys.push( key + " " ) > Expr.cacheLength ) {
- // Only keep the most recent entries
- delete cache[ keys.shift() ];
- }
- return (cache[ key + " " ] = value);
- }
- return cache;
-}
-
-/**
- * Mark a function for special use by Sizzle
- * @param {Function} fn The function to mark
- */
-function markFunction( fn ) {
- fn[ expando ] = true;
- return fn;
-}
-
-/**
- * Support testing using an element
- * @param {Function} fn Passed the created element and returns a boolean result
- */
-function assert( fn ) {
- var el = document.createElement("fieldset");
-
- try {
- return !!fn( el );
- } catch (e) {
- return false;
- } finally {
- // Remove from its parent by default
- if ( el.parentNode ) {
- el.parentNode.removeChild( el );
- }
- // release memory in IE
- el = null;
- }
-}
-
-/**
- * Adds the same handler for all of the specified attrs
- * @param {String} attrs Pipe-separated list of attributes
- * @param {Function} handler The method that will be applied
- */
-function addHandle( attrs, handler ) {
- var arr = attrs.split("|"),
- i = arr.length;
-
- while ( i-- ) {
- Expr.attrHandle[ arr[i] ] = handler;
- }
-}
-
-/**
- * Checks document order of two siblings
- * @param {Element} a
- * @param {Element} b
- * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
- */
-function siblingCheck( a, b ) {
- var cur = b && a,
- diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
- a.sourceIndex - b.sourceIndex;
-
- // Use IE sourceIndex if available on both nodes
- if ( diff ) {
- return diff;
- }
-
- // Check if b follows a
- if ( cur ) {
- while ( (cur = cur.nextSibling) ) {
- if ( cur === b ) {
- return -1;
- }
- }
- }
-
- return a ? 1 : -1;
-}
-
-/**
- * Returns a function to use in pseudos for input types
- * @param {String} type
- */
-function createInputPseudo( type ) {
- return function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && elem.type === type;
- };
-}
-
-/**
- * Returns a function to use in pseudos for buttons
- * @param {String} type
- */
-function createButtonPseudo( type ) {
- return function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return (name === "input" || name === "button") && elem.type === type;
- };
-}
-
-/**
- * Returns a function to use in pseudos for :enabled/:disabled
- * @param {Boolean} disabled true for :disabled; false for :enabled
- */
-function createDisabledPseudo( disabled ) {
-
- // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
- return function( elem ) {
-
- // Only certain elements can match :enabled or :disabled
- // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
- // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
- if ( "form" in elem ) {
-
- // Check for inherited disabledness on relevant non-disabled elements:
- // * listed form-associated elements in a disabled fieldset
- // https://html.spec.whatwg.org/multipage/forms.html#category-listed
- // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
- // * option elements in a disabled optgroup
- // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
- // All such elements have a "form" property.
- if ( elem.parentNode && elem.disabled === false ) {
-
- // Option elements defer to a parent optgroup if present
- if ( "label" in elem ) {
- if ( "label" in elem.parentNode ) {
- return elem.parentNode.disabled === disabled;
- } else {
- return elem.disabled === disabled;
- }
- }
-
- // Support: IE 6 - 11
- // Use the isDisabled shortcut property to check for disabled fieldset ancestors
- return elem.isDisabled === disabled ||
-
- // Where there is no isDisabled, check manually
- /* jshint -W018 */
- elem.isDisabled !== !disabled &&
- inDisabledFieldset( elem ) === disabled;
- }
-
- return elem.disabled === disabled;
-
- // Try to winnow out elements that can't be disabled before trusting the disabled property.
- // Some victims get caught in our net (label, legend, menu, track), but it shouldn't
- // even exist on them, let alone have a boolean value.
- } else if ( "label" in elem ) {
- return elem.disabled === disabled;
- }
-
- // Remaining elements are neither :enabled nor :disabled
- return false;
- };
-}
-
-/**
- * Returns a function to use in pseudos for positionals
- * @param {Function} fn
- */
-function createPositionalPseudo( fn ) {
- return markFunction(function( argument ) {
- argument = +argument;
- return markFunction(function( seed, matches ) {
- var j,
- matchIndexes = fn( [], seed.length, argument ),
- i = matchIndexes.length;
-
- // Match elements found at the specified indexes
- while ( i-- ) {
- if ( seed[ (j = matchIndexes[i]) ] ) {
- seed[j] = !(matches[j] = seed[j]);
- }
- }
- });
- });
-}
-
-/**
- * Checks a node for validity as a Sizzle context
- * @param {Element|Object=} context
- * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
- */
-function testContext( context ) {
- return context && typeof context.getElementsByTagName !== "undefined" && context;
-}
-
-// Expose support vars for convenience
-support = Sizzle.support = {};
-
-/**
- * Detects XML nodes
- * @param {Element|Object} elem An element or a document
- * @returns {Boolean} True iff elem is a non-HTML XML node
- */
-isXML = Sizzle.isXML = function( elem ) {
- var namespace = elem.namespaceURI,
- docElem = (elem.ownerDocument || elem).documentElement;
-
- // Support: IE <=8
- // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes
- // https://bugs.jquery.com/ticket/4833
- return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" );
-};
-
-/**
- * Sets document-related variables once based on the current document
- * @param {Element|Object} [doc] An element or document object to use to set the document
- * @returns {Object} Returns the current document
- */
-setDocument = Sizzle.setDocument = function( node ) {
- var hasCompare, subWindow,
- doc = node ? node.ownerDocument || node : preferredDoc;
-
- // Return early if doc is invalid or already selected
- if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
- return document;
- }
-
- // Update global variables
- document = doc;
- docElem = document.documentElement;
- documentIsHTML = !isXML( document );
-
- // Support: IE 9-11, Edge
- // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
- if ( preferredDoc !== document &&
- (subWindow = document.defaultView) && subWindow.top !== subWindow ) {
-
- // Support: IE 11, Edge
- if ( subWindow.addEventListener ) {
- subWindow.addEventListener( "unload", unloadHandler, false );
-
- // Support: IE 9 - 10 only
- } else if ( subWindow.attachEvent ) {
- subWindow.attachEvent( "onunload", unloadHandler );
- }
- }
-
- /* Attributes
- ---------------------------------------------------------------------- */
-
- // Support: IE<8
- // Verify that getAttribute really returns attributes and not properties
- // (excepting IE8 booleans)
- support.attributes = assert(function( el ) {
- el.className = "i";
- return !el.getAttribute("className");
- });
-
- /* getElement(s)By*
- ---------------------------------------------------------------------- */
-
- // Check if getElementsByTagName("*") returns only elements
- support.getElementsByTagName = assert(function( el ) {
- el.appendChild( document.createComment("") );
- return !el.getElementsByTagName("*").length;
- });
-
- // Support: IE<9
- support.getElementsByClassName = rnative.test( document.getElementsByClassName );
-
- // Support: IE<10
- // Check if getElementById returns elements by name
- // The broken getElementById methods don't pick up programmatically-set names,
- // so use a roundabout getElementsByName test
- support.getById = assert(function( el ) {
- docElem.appendChild( el ).id = expando;
- return !document.getElementsByName || !document.getElementsByName( expando ).length;
- });
-
- // ID filter and find
- if ( support.getById ) {
- Expr.filter["ID"] = function( id ) {
- var attrId = id.replace( runescape, funescape );
- return function( elem ) {
- return elem.getAttribute("id") === attrId;
- };
- };
- Expr.find["ID"] = function( id, context ) {
- if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
- var elem = context.getElementById( id );
- return elem ? [ elem ] : [];
- }
- };
- } else {
- Expr.filter["ID"] = function( id ) {
- var attrId = id.replace( runescape, funescape );
- return function( elem ) {
- var node = typeof elem.getAttributeNode !== "undefined" &&
- elem.getAttributeNode("id");
- return node && node.value === attrId;
- };
- };
-
- // Support: IE 6 - 7 only
- // getElementById is not reliable as a find shortcut
- Expr.find["ID"] = function( id, context ) {
- if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
- var node, i, elems,
- elem = context.getElementById( id );
-
- if ( elem ) {
-
- // Verify the id attribute
- node = elem.getAttributeNode("id");
- if ( node && node.value === id ) {
- return [ elem ];
- }
-
- // Fall back on getElementsByName
- elems = context.getElementsByName( id );
- i = 0;
- while ( (elem = elems[i++]) ) {
- node = elem.getAttributeNode("id");
- if ( node && node.value === id ) {
- return [ elem ];
- }
- }
- }
-
- return [];
- }
- };
- }
-
- // Tag
- Expr.find["TAG"] = support.getElementsByTagName ?
- function( tag, context ) {
- if ( typeof context.getElementsByTagName !== "undefined" ) {
- return context.getElementsByTagName( tag );
-
- // DocumentFragment nodes don't have gEBTN
- } else if ( support.qsa ) {
- return context.querySelectorAll( tag );
- }
- } :
-
- function( tag, context ) {
- var elem,
- tmp = [],
- i = 0,
- // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
- results = context.getElementsByTagName( tag );
-
- // Filter out possible comments
- if ( tag === "*" ) {
- while ( (elem = results[i++]) ) {
- if ( elem.nodeType === 1 ) {
- tmp.push( elem );
- }
- }
-
- return tmp;
- }
- return results;
- };
-
- // Class
- Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
- if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
- return context.getElementsByClassName( className );
- }
- };
-
- /* QSA/matchesSelector
- ---------------------------------------------------------------------- */
-
- // QSA and matchesSelector support
-
- // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
- rbuggyMatches = [];
-
- // qSa(:focus) reports false when true (Chrome 21)
- // We allow this because of a bug in IE8/9 that throws an error
- // whenever `document.activeElement` is accessed on an iframe
- // So, we allow :focus to pass through QSA all the time to avoid the IE error
- // See https://bugs.jquery.com/ticket/13378
- rbuggyQSA = [];
-
- if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
- // Build QSA regex
- // Regex strategy adopted from Diego Perini
- assert(function( el ) {
- // Select is set to empty string on purpose
- // This is to test IE's treatment of not explicitly
- // setting a boolean content attribute,
- // since its presence should be enough
- // https://bugs.jquery.com/ticket/12359
- docElem.appendChild( el ).innerHTML = " " +
- "" +
- " ";
-
- // Support: IE8, Opera 11-12.16
- // Nothing should be selected when empty strings follow ^= or $= or *=
- // The test attribute must be unknown in Opera but "safe" for WinRT
- // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
- if ( el.querySelectorAll("[msallowcapture^='']").length ) {
- rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
- }
-
- // Support: IE8
- // Boolean attributes and "value" are not treated correctly
- if ( !el.querySelectorAll("[selected]").length ) {
- rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
- }
-
- // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
- if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
- rbuggyQSA.push("~=");
- }
-
- // Webkit/Opera - :checked should return selected option elements
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
- // IE8 throws error here and will not see later tests
- if ( !el.querySelectorAll(":checked").length ) {
- rbuggyQSA.push(":checked");
- }
-
- // Support: Safari 8+, iOS 8+
- // https://bugs.webkit.org/show_bug.cgi?id=136851
- // In-page `selector#id sibling-combinator selector` fails
- if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
- rbuggyQSA.push(".#.+[+~]");
- }
- });
-
- assert(function( el ) {
- el.innerHTML = " " +
- " ";
-
- // Support: Windows 8 Native Apps
- // The type and name attributes are restricted during .innerHTML assignment
- var input = document.createElement("input");
- input.setAttribute( "type", "hidden" );
- el.appendChild( input ).setAttribute( "name", "D" );
-
- // Support: IE8
- // Enforce case-sensitivity of name attribute
- if ( el.querySelectorAll("[name=d]").length ) {
- rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
- }
-
- // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
- // IE8 throws error here and will not see later tests
- if ( el.querySelectorAll(":enabled").length !== 2 ) {
- rbuggyQSA.push( ":enabled", ":disabled" );
- }
-
- // Support: IE9-11+
- // IE's :disabled selector does not pick up the children of disabled fieldsets
- docElem.appendChild( el ).disabled = true;
- if ( el.querySelectorAll(":disabled").length !== 2 ) {
- rbuggyQSA.push( ":enabled", ":disabled" );
- }
-
- // Opera 10-11 does not throw on post-comma invalid pseudos
- el.querySelectorAll("*,:x");
- rbuggyQSA.push(",.*:");
- });
- }
-
- if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
- docElem.webkitMatchesSelector ||
- docElem.mozMatchesSelector ||
- docElem.oMatchesSelector ||
- docElem.msMatchesSelector) )) ) {
-
- assert(function( el ) {
- // Check to see if it's possible to do matchesSelector
- // on a disconnected node (IE 9)
- support.disconnectedMatch = matches.call( el, "*" );
-
- // This should fail with an exception
- // Gecko does not error, returns false instead
- matches.call( el, "[s!='']:x" );
- rbuggyMatches.push( "!=", pseudos );
- });
- }
-
- rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
- rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
-
- /* Contains
- ---------------------------------------------------------------------- */
- hasCompare = rnative.test( docElem.compareDocumentPosition );
-
- // Element contains another
- // Purposefully self-exclusive
- // As in, an element does not contain itself
- contains = hasCompare || rnative.test( docElem.contains ) ?
- function( a, b ) {
- var adown = a.nodeType === 9 ? a.documentElement : a,
- bup = b && b.parentNode;
- return a === bup || !!( bup && bup.nodeType === 1 && (
- adown.contains ?
- adown.contains( bup ) :
- a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
- ));
- } :
- function( a, b ) {
- if ( b ) {
- while ( (b = b.parentNode) ) {
- if ( b === a ) {
- return true;
- }
- }
- }
- return false;
- };
-
- /* Sorting
- ---------------------------------------------------------------------- */
-
- // Document order sorting
- sortOrder = hasCompare ?
- function( a, b ) {
-
- // Flag for duplicate removal
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
-
- // Sort on method existence if only one input has compareDocumentPosition
- var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
- if ( compare ) {
- return compare;
- }
-
- // Calculate position if both inputs belong to the same document
- compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
- a.compareDocumentPosition( b ) :
-
- // Otherwise we know they are disconnected
- 1;
-
- // Disconnected nodes
- if ( compare & 1 ||
- (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
-
- // Choose the first element that is related to our preferred document
- if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
- return -1;
- }
- if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
- return 1;
- }
-
- // Maintain original order
- return sortInput ?
- ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
- 0;
- }
-
- return compare & 4 ? -1 : 1;
- } :
- function( a, b ) {
- // Exit early if the nodes are identical
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
-
- var cur,
- i = 0,
- aup = a.parentNode,
- bup = b.parentNode,
- ap = [ a ],
- bp = [ b ];
-
- // Parentless nodes are either documents or disconnected
- if ( !aup || !bup ) {
- return a === document ? -1 :
- b === document ? 1 :
- aup ? -1 :
- bup ? 1 :
- sortInput ?
- ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
- 0;
-
- // If the nodes are siblings, we can do a quick check
- } else if ( aup === bup ) {
- return siblingCheck( a, b );
- }
-
- // Otherwise we need full lists of their ancestors for comparison
- cur = a;
- while ( (cur = cur.parentNode) ) {
- ap.unshift( cur );
- }
- cur = b;
- while ( (cur = cur.parentNode) ) {
- bp.unshift( cur );
- }
-
- // Walk down the tree looking for a discrepancy
- while ( ap[i] === bp[i] ) {
- i++;
- }
-
- return i ?
- // Do a sibling check if the nodes have a common ancestor
- siblingCheck( ap[i], bp[i] ) :
-
- // Otherwise nodes in our document sort first
- ap[i] === preferredDoc ? -1 :
- bp[i] === preferredDoc ? 1 :
- 0;
- };
-
- return document;
-};
-
-Sizzle.matches = function( expr, elements ) {
- return Sizzle( expr, null, null, elements );
-};
-
-Sizzle.matchesSelector = function( elem, expr ) {
- // Set document vars if needed
- if ( ( elem.ownerDocument || elem ) !== document ) {
- setDocument( elem );
- }
-
- if ( support.matchesSelector && documentIsHTML &&
- !nonnativeSelectorCache[ expr + " " ] &&
- ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
- ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
-
- try {
- var ret = matches.call( elem, expr );
-
- // IE 9's matchesSelector returns false on disconnected nodes
- if ( ret || support.disconnectedMatch ||
- // As well, disconnected nodes are said to be in a document
- // fragment in IE 9
- elem.document && elem.document.nodeType !== 11 ) {
- return ret;
- }
- } catch (e) {
- nonnativeSelectorCache( expr, true );
- }
- }
-
- return Sizzle( expr, document, null, [ elem ] ).length > 0;
-};
-
-Sizzle.contains = function( context, elem ) {
- // Set document vars if needed
- if ( ( context.ownerDocument || context ) !== document ) {
- setDocument( context );
- }
- return contains( context, elem );
-};
-
-Sizzle.attr = function( elem, name ) {
- // Set document vars if needed
- if ( ( elem.ownerDocument || elem ) !== document ) {
- setDocument( elem );
- }
-
- var fn = Expr.attrHandle[ name.toLowerCase() ],
- // Don't get fooled by Object.prototype properties (jQuery #13807)
- val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
- fn( elem, name, !documentIsHTML ) :
- undefined;
-
- return val !== undefined ?
- val :
- support.attributes || !documentIsHTML ?
- elem.getAttribute( name ) :
- (val = elem.getAttributeNode(name)) && val.specified ?
- val.value :
- null;
-};
-
-Sizzle.escape = function( sel ) {
- return (sel + "").replace( rcssescape, fcssescape );
-};
-
-Sizzle.error = function( msg ) {
- throw new Error( "Syntax error, unrecognized expression: " + msg );
-};
-
-/**
- * Document sorting and removing duplicates
- * @param {ArrayLike} results
- */
-Sizzle.uniqueSort = function( results ) {
- var elem,
- duplicates = [],
- j = 0,
- i = 0;
-
- // Unless we *know* we can detect duplicates, assume their presence
- hasDuplicate = !support.detectDuplicates;
- sortInput = !support.sortStable && results.slice( 0 );
- results.sort( sortOrder );
-
- if ( hasDuplicate ) {
- while ( (elem = results[i++]) ) {
- if ( elem === results[ i ] ) {
- j = duplicates.push( i );
- }
- }
- while ( j-- ) {
- results.splice( duplicates[ j ], 1 );
- }
- }
-
- // Clear input after sorting to release objects
- // See https://github.com/jquery/sizzle/pull/225
- sortInput = null;
-
- return results;
-};
-
-/**
- * Utility function for retrieving the text value of an array of DOM nodes
- * @param {Array|Element} elem
- */
-getText = Sizzle.getText = function( elem ) {
- var node,
- ret = "",
- i = 0,
- nodeType = elem.nodeType;
-
- if ( !nodeType ) {
- // If no nodeType, this is expected to be an array
- while ( (node = elem[i++]) ) {
- // Do not traverse comment nodes
- ret += getText( node );
- }
- } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
- // Use textContent for elements
- // innerText usage removed for consistency of new lines (jQuery #11153)
- if ( typeof elem.textContent === "string" ) {
- return elem.textContent;
- } else {
- // Traverse its children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
- ret += getText( elem );
- }
- }
- } else if ( nodeType === 3 || nodeType === 4 ) {
- return elem.nodeValue;
- }
- // Do not include comment or processing instruction nodes
-
- return ret;
-};
-
-Expr = Sizzle.selectors = {
-
- // Can be adjusted by the user
- cacheLength: 50,
-
- createPseudo: markFunction,
-
- match: matchExpr,
-
- attrHandle: {},
-
- find: {},
-
- relative: {
- ">": { dir: "parentNode", first: true },
- " ": { dir: "parentNode" },
- "+": { dir: "previousSibling", first: true },
- "~": { dir: "previousSibling" }
- },
-
- preFilter: {
- "ATTR": function( match ) {
- match[1] = match[1].replace( runescape, funescape );
-
- // Move the given value to match[3] whether quoted or unquoted
- match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
-
- if ( match[2] === "~=" ) {
- match[3] = " " + match[3] + " ";
- }
-
- return match.slice( 0, 4 );
- },
-
- "CHILD": function( match ) {
- /* matches from matchExpr["CHILD"]
- 1 type (only|nth|...)
- 2 what (child|of-type)
- 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
- 4 xn-component of xn+y argument ([+-]?\d*n|)
- 5 sign of xn-component
- 6 x of xn-component
- 7 sign of y-component
- 8 y of y-component
- */
- match[1] = match[1].toLowerCase();
-
- if ( match[1].slice( 0, 3 ) === "nth" ) {
- // nth-* requires argument
- if ( !match[3] ) {
- Sizzle.error( match[0] );
- }
-
- // numeric x and y parameters for Expr.filter.CHILD
- // remember that false/true cast respectively to 0/1
- match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
- match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
-
- // other types prohibit arguments
- } else if ( match[3] ) {
- Sizzle.error( match[0] );
- }
-
- return match;
- },
-
- "PSEUDO": function( match ) {
- var excess,
- unquoted = !match[6] && match[2];
-
- if ( matchExpr["CHILD"].test( match[0] ) ) {
- return null;
- }
-
- // Accept quoted arguments as-is
- if ( match[3] ) {
- match[2] = match[4] || match[5] || "";
-
- // Strip excess characters from unquoted arguments
- } else if ( unquoted && rpseudo.test( unquoted ) &&
- // Get excess from tokenize (recursively)
- (excess = tokenize( unquoted, true )) &&
- // advance to the next closing parenthesis
- (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
-
- // excess is a negative index
- match[0] = match[0].slice( 0, excess );
- match[2] = unquoted.slice( 0, excess );
- }
-
- // Return only captures needed by the pseudo filter method (type and argument)
- return match.slice( 0, 3 );
- }
- },
-
- filter: {
-
- "TAG": function( nodeNameSelector ) {
- var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
- return nodeNameSelector === "*" ?
- function() { return true; } :
- function( elem ) {
- return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
- };
- },
-
- "CLASS": function( className ) {
- var pattern = classCache[ className + " " ];
-
- return pattern ||
- (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
- classCache( className, function( elem ) {
- return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
- });
- },
-
- "ATTR": function( name, operator, check ) {
- return function( elem ) {
- var result = Sizzle.attr( elem, name );
-
- if ( result == null ) {
- return operator === "!=";
- }
- if ( !operator ) {
- return true;
- }
-
- result += "";
-
- return operator === "=" ? result === check :
- operator === "!=" ? result !== check :
- operator === "^=" ? check && result.indexOf( check ) === 0 :
- operator === "*=" ? check && result.indexOf( check ) > -1 :
- operator === "$=" ? check && result.slice( -check.length ) === check :
- operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
- operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
- false;
- };
- },
-
- "CHILD": function( type, what, argument, first, last ) {
- var simple = type.slice( 0, 3 ) !== "nth",
- forward = type.slice( -4 ) !== "last",
- ofType = what === "of-type";
-
- return first === 1 && last === 0 ?
-
- // Shortcut for :nth-*(n)
- function( elem ) {
- return !!elem.parentNode;
- } :
-
- function( elem, context, xml ) {
- var cache, uniqueCache, outerCache, node, nodeIndex, start,
- dir = simple !== forward ? "nextSibling" : "previousSibling",
- parent = elem.parentNode,
- name = ofType && elem.nodeName.toLowerCase(),
- useCache = !xml && !ofType,
- diff = false;
-
- if ( parent ) {
-
- // :(first|last|only)-(child|of-type)
- if ( simple ) {
- while ( dir ) {
- node = elem;
- while ( (node = node[ dir ]) ) {
- if ( ofType ?
- node.nodeName.toLowerCase() === name :
- node.nodeType === 1 ) {
-
- return false;
- }
- }
- // Reverse direction for :only-* (if we haven't yet done so)
- start = dir = type === "only" && !start && "nextSibling";
- }
- return true;
- }
-
- start = [ forward ? parent.firstChild : parent.lastChild ];
-
- // non-xml :nth-child(...) stores cache data on `parent`
- if ( forward && useCache ) {
-
- // Seek `elem` from a previously-cached index
-
- // ...in a gzip-friendly way
- node = parent;
- outerCache = node[ expando ] || (node[ expando ] = {});
-
- // Support: IE <9 only
- // Defend against cloned attroperties (jQuery gh-1709)
- uniqueCache = outerCache[ node.uniqueID ] ||
- (outerCache[ node.uniqueID ] = {});
-
- cache = uniqueCache[ type ] || [];
- nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
- diff = nodeIndex && cache[ 2 ];
- node = nodeIndex && parent.childNodes[ nodeIndex ];
-
- while ( (node = ++nodeIndex && node && node[ dir ] ||
-
- // Fallback to seeking `elem` from the start
- (diff = nodeIndex = 0) || start.pop()) ) {
-
- // When found, cache indexes on `parent` and break
- if ( node.nodeType === 1 && ++diff && node === elem ) {
- uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
- break;
- }
- }
-
- } else {
- // Use previously-cached element index if available
- if ( useCache ) {
- // ...in a gzip-friendly way
- node = elem;
- outerCache = node[ expando ] || (node[ expando ] = {});
-
- // Support: IE <9 only
- // Defend against cloned attroperties (jQuery gh-1709)
- uniqueCache = outerCache[ node.uniqueID ] ||
- (outerCache[ node.uniqueID ] = {});
-
- cache = uniqueCache[ type ] || [];
- nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
- diff = nodeIndex;
- }
-
- // xml :nth-child(...)
- // or :nth-last-child(...) or :nth(-last)?-of-type(...)
- if ( diff === false ) {
- // Use the same loop as above to seek `elem` from the start
- while ( (node = ++nodeIndex && node && node[ dir ] ||
- (diff = nodeIndex = 0) || start.pop()) ) {
-
- if ( ( ofType ?
- node.nodeName.toLowerCase() === name :
- node.nodeType === 1 ) &&
- ++diff ) {
-
- // Cache the index of each encountered element
- if ( useCache ) {
- outerCache = node[ expando ] || (node[ expando ] = {});
-
- // Support: IE <9 only
- // Defend against cloned attroperties (jQuery gh-1709)
- uniqueCache = outerCache[ node.uniqueID ] ||
- (outerCache[ node.uniqueID ] = {});
-
- uniqueCache[ type ] = [ dirruns, diff ];
- }
-
- if ( node === elem ) {
- break;
- }
- }
- }
- }
- }
-
- // Incorporate the offset, then check against cycle size
- diff -= last;
- return diff === first || ( diff % first === 0 && diff / first >= 0 );
- }
- };
- },
-
- "PSEUDO": function( pseudo, argument ) {
- // pseudo-class names are case-insensitive
- // http://www.w3.org/TR/selectors/#pseudo-classes
- // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
- // Remember that setFilters inherits from pseudos
- var args,
- fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
- Sizzle.error( "unsupported pseudo: " + pseudo );
-
- // The user may use createPseudo to indicate that
- // arguments are needed to create the filter function
- // just as Sizzle does
- if ( fn[ expando ] ) {
- return fn( argument );
- }
-
- // But maintain support for old signatures
- if ( fn.length > 1 ) {
- args = [ pseudo, pseudo, "", argument ];
- return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
- markFunction(function( seed, matches ) {
- var idx,
- matched = fn( seed, argument ),
- i = matched.length;
- while ( i-- ) {
- idx = indexOf( seed, matched[i] );
- seed[ idx ] = !( matches[ idx ] = matched[i] );
- }
- }) :
- function( elem ) {
- return fn( elem, 0, args );
- };
- }
-
- return fn;
- }
- },
-
- pseudos: {
- // Potentially complex pseudos
- "not": markFunction(function( selector ) {
- // Trim the selector passed to compile
- // to avoid treating leading and trailing
- // spaces as combinators
- var input = [],
- results = [],
- matcher = compile( selector.replace( rtrim, "$1" ) );
-
- return matcher[ expando ] ?
- markFunction(function( seed, matches, context, xml ) {
- var elem,
- unmatched = matcher( seed, null, xml, [] ),
- i = seed.length;
-
- // Match elements unmatched by `matcher`
- while ( i-- ) {
- if ( (elem = unmatched[i]) ) {
- seed[i] = !(matches[i] = elem);
- }
- }
- }) :
- function( elem, context, xml ) {
- input[0] = elem;
- matcher( input, null, xml, results );
- // Don't keep the element (issue #299)
- input[0] = null;
- return !results.pop();
- };
- }),
-
- "has": markFunction(function( selector ) {
- return function( elem ) {
- return Sizzle( selector, elem ).length > 0;
- };
- }),
-
- "contains": markFunction(function( text ) {
- text = text.replace( runescape, funescape );
- return function( elem ) {
- return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1;
- };
- }),
-
- // "Whether an element is represented by a :lang() selector
- // is based solely on the element's language value
- // being equal to the identifier C,
- // or beginning with the identifier C immediately followed by "-".
- // The matching of C against the element's language value is performed case-insensitively.
- // The identifier C does not have to be a valid language name."
- // http://www.w3.org/TR/selectors/#lang-pseudo
- "lang": markFunction( function( lang ) {
- // lang value must be a valid identifier
- if ( !ridentifier.test(lang || "") ) {
- Sizzle.error( "unsupported lang: " + lang );
- }
- lang = lang.replace( runescape, funescape ).toLowerCase();
- return function( elem ) {
- var elemLang;
- do {
- if ( (elemLang = documentIsHTML ?
- elem.lang :
- elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
-
- elemLang = elemLang.toLowerCase();
- return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
- }
- } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
- return false;
- };
- }),
-
- // Miscellaneous
- "target": function( elem ) {
- var hash = window.location && window.location.hash;
- return hash && hash.slice( 1 ) === elem.id;
- },
-
- "root": function( elem ) {
- return elem === docElem;
- },
-
- "focus": function( elem ) {
- return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
- },
-
- // Boolean properties
- "enabled": createDisabledPseudo( false ),
- "disabled": createDisabledPseudo( true ),
-
- "checked": function( elem ) {
- // In CSS3, :checked should return both checked and selected elements
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
- var nodeName = elem.nodeName.toLowerCase();
- return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
- },
-
- "selected": function( elem ) {
- // Accessing this property makes selected-by-default
- // options in Safari work properly
- if ( elem.parentNode ) {
- elem.parentNode.selectedIndex;
- }
-
- return elem.selected === true;
- },
-
- // Contents
- "empty": function( elem ) {
- // http://www.w3.org/TR/selectors/#empty-pseudo
- // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
- // but not by others (comment: 8; processing instruction: 7; etc.)
- // nodeType < 6 works because attributes (2) do not appear as children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
- if ( elem.nodeType < 6 ) {
- return false;
- }
- }
- return true;
- },
-
- "parent": function( elem ) {
- return !Expr.pseudos["empty"]( elem );
- },
-
- // Element/input types
- "header": function( elem ) {
- return rheader.test( elem.nodeName );
- },
-
- "input": function( elem ) {
- return rinputs.test( elem.nodeName );
- },
-
- "button": function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && elem.type === "button" || name === "button";
- },
-
- "text": function( elem ) {
- var attr;
- return elem.nodeName.toLowerCase() === "input" &&
- elem.type === "text" &&
-
- // Support: IE<8
- // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
- ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
- },
-
- // Position-in-collection
- "first": createPositionalPseudo(function() {
- return [ 0 ];
- }),
-
- "last": createPositionalPseudo(function( matchIndexes, length ) {
- return [ length - 1 ];
- }),
-
- "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
- return [ argument < 0 ? argument + length : argument ];
- }),
-
- "even": createPositionalPseudo(function( matchIndexes, length ) {
- var i = 0;
- for ( ; i < length; i += 2 ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
-
- "odd": createPositionalPseudo(function( matchIndexes, length ) {
- var i = 1;
- for ( ; i < length; i += 2 ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
-
- "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
- var i = argument < 0 ?
- argument + length :
- argument > length ?
- length :
- argument;
- for ( ; --i >= 0; ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
-
- "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
- var i = argument < 0 ? argument + length : argument;
- for ( ; ++i < length; ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- })
- }
-};
-
-Expr.pseudos["nth"] = Expr.pseudos["eq"];
-
-// Add button/input type pseudos
-for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
- Expr.pseudos[ i ] = createInputPseudo( i );
-}
-for ( i in { submit: true, reset: true } ) {
- Expr.pseudos[ i ] = createButtonPseudo( i );
-}
-
-// Easy API for creating new setFilters
-function setFilters() {}
-setFilters.prototype = Expr.filters = Expr.pseudos;
-Expr.setFilters = new setFilters();
-
-tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
- var matched, match, tokens, type,
- soFar, groups, preFilters,
- cached = tokenCache[ selector + " " ];
-
- if ( cached ) {
- return parseOnly ? 0 : cached.slice( 0 );
- }
-
- soFar = selector;
- groups = [];
- preFilters = Expr.preFilter;
-
- while ( soFar ) {
-
- // Comma and first run
- if ( !matched || (match = rcomma.exec( soFar )) ) {
- if ( match ) {
- // Don't consume trailing commas as valid
- soFar = soFar.slice( match[0].length ) || soFar;
- }
- groups.push( (tokens = []) );
- }
-
- matched = false;
-
- // Combinators
- if ( (match = rcombinators.exec( soFar )) ) {
- matched = match.shift();
- tokens.push({
- value: matched,
- // Cast descendant combinators to space
- type: match[0].replace( rtrim, " " )
- });
- soFar = soFar.slice( matched.length );
- }
-
- // Filters
- for ( type in Expr.filter ) {
- if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
- (match = preFilters[ type ]( match ))) ) {
- matched = match.shift();
- tokens.push({
- value: matched,
- type: type,
- matches: match
- });
- soFar = soFar.slice( matched.length );
- }
- }
-
- if ( !matched ) {
- break;
- }
- }
-
- // Return the length of the invalid excess
- // if we're just parsing
- // Otherwise, throw an error or return tokens
- return parseOnly ?
- soFar.length :
- soFar ?
- Sizzle.error( selector ) :
- // Cache the tokens
- tokenCache( selector, groups ).slice( 0 );
-};
-
-function toSelector( tokens ) {
- var i = 0,
- len = tokens.length,
- selector = "";
- for ( ; i < len; i++ ) {
- selector += tokens[i].value;
- }
- return selector;
-}
-
-function addCombinator( matcher, combinator, base ) {
- var dir = combinator.dir,
- skip = combinator.next,
- key = skip || dir,
- checkNonElements = base && key === "parentNode",
- doneName = done++;
-
- return combinator.first ?
- // Check against closest ancestor/preceding element
- function( elem, context, xml ) {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- return matcher( elem, context, xml );
- }
- }
- return false;
- } :
-
- // Check against all ancestor/preceding elements
- function( elem, context, xml ) {
- var oldCache, uniqueCache, outerCache,
- newCache = [ dirruns, doneName ];
-
- // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
- if ( xml ) {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- if ( matcher( elem, context, xml ) ) {
- return true;
- }
- }
- }
- } else {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- outerCache = elem[ expando ] || (elem[ expando ] = {});
-
- // Support: IE <9 only
- // Defend against cloned attroperties (jQuery gh-1709)
- uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
-
- if ( skip && skip === elem.nodeName.toLowerCase() ) {
- elem = elem[ dir ] || elem;
- } else if ( (oldCache = uniqueCache[ key ]) &&
- oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
-
- // Assign to newCache so results back-propagate to previous elements
- return (newCache[ 2 ] = oldCache[ 2 ]);
- } else {
- // Reuse newcache so results back-propagate to previous elements
- uniqueCache[ key ] = newCache;
-
- // A match means we're done; a fail means we have to keep checking
- if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
- return true;
- }
- }
- }
- }
- }
- return false;
- };
-}
-
-function elementMatcher( matchers ) {
- return matchers.length > 1 ?
- function( elem, context, xml ) {
- var i = matchers.length;
- while ( i-- ) {
- if ( !matchers[i]( elem, context, xml ) ) {
- return false;
- }
- }
- return true;
- } :
- matchers[0];
-}
-
-function multipleContexts( selector, contexts, results ) {
- var i = 0,
- len = contexts.length;
- for ( ; i < len; i++ ) {
- Sizzle( selector, contexts[i], results );
- }
- return results;
-}
-
-function condense( unmatched, map, filter, context, xml ) {
- var elem,
- newUnmatched = [],
- i = 0,
- len = unmatched.length,
- mapped = map != null;
-
- for ( ; i < len; i++ ) {
- if ( (elem = unmatched[i]) ) {
- if ( !filter || filter( elem, context, xml ) ) {
- newUnmatched.push( elem );
- if ( mapped ) {
- map.push( i );
- }
- }
- }
- }
-
- return newUnmatched;
-}
-
-function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
- if ( postFilter && !postFilter[ expando ] ) {
- postFilter = setMatcher( postFilter );
- }
- if ( postFinder && !postFinder[ expando ] ) {
- postFinder = setMatcher( postFinder, postSelector );
- }
- return markFunction(function( seed, results, context, xml ) {
- var temp, i, elem,
- preMap = [],
- postMap = [],
- preexisting = results.length,
-
- // Get initial elements from seed or context
- elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
-
- // Prefilter to get matcher input, preserving a map for seed-results synchronization
- matcherIn = preFilter && ( seed || !selector ) ?
- condense( elems, preMap, preFilter, context, xml ) :
- elems,
-
- matcherOut = matcher ?
- // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
- postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
-
- // ...intermediate processing is necessary
- [] :
-
- // ...otherwise use results directly
- results :
- matcherIn;
-
- // Find primary matches
- if ( matcher ) {
- matcher( matcherIn, matcherOut, context, xml );
- }
-
- // Apply postFilter
- if ( postFilter ) {
- temp = condense( matcherOut, postMap );
- postFilter( temp, [], context, xml );
-
- // Un-match failing elements by moving them back to matcherIn
- i = temp.length;
- while ( i-- ) {
- if ( (elem = temp[i]) ) {
- matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
- }
- }
- }
-
- if ( seed ) {
- if ( postFinder || preFilter ) {
- if ( postFinder ) {
- // Get the final matcherOut by condensing this intermediate into postFinder contexts
- temp = [];
- i = matcherOut.length;
- while ( i-- ) {
- if ( (elem = matcherOut[i]) ) {
- // Restore matcherIn since elem is not yet a final match
- temp.push( (matcherIn[i] = elem) );
- }
- }
- postFinder( null, (matcherOut = []), temp, xml );
- }
-
- // Move matched elements from seed to results to keep them synchronized
- i = matcherOut.length;
- while ( i-- ) {
- if ( (elem = matcherOut[i]) &&
- (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
-
- seed[temp] = !(results[temp] = elem);
- }
- }
- }
-
- // Add elements to results, through postFinder if defined
- } else {
- matcherOut = condense(
- matcherOut === results ?
- matcherOut.splice( preexisting, matcherOut.length ) :
- matcherOut
- );
- if ( postFinder ) {
- postFinder( null, results, matcherOut, xml );
- } else {
- push.apply( results, matcherOut );
- }
- }
- });
-}
-
-function matcherFromTokens( tokens ) {
- var checkContext, matcher, j,
- len = tokens.length,
- leadingRelative = Expr.relative[ tokens[0].type ],
- implicitRelative = leadingRelative || Expr.relative[" "],
- i = leadingRelative ? 1 : 0,
-
- // The foundational matcher ensures that elements are reachable from top-level context(s)
- matchContext = addCombinator( function( elem ) {
- return elem === checkContext;
- }, implicitRelative, true ),
- matchAnyContext = addCombinator( function( elem ) {
- return indexOf( checkContext, elem ) > -1;
- }, implicitRelative, true ),
- matchers = [ function( elem, context, xml ) {
- var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
- (checkContext = context).nodeType ?
- matchContext( elem, context, xml ) :
- matchAnyContext( elem, context, xml ) );
- // Avoid hanging onto element (issue #299)
- checkContext = null;
- return ret;
- } ];
-
- for ( ; i < len; i++ ) {
- if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
- matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
- } else {
- matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
-
- // Return special upon seeing a positional matcher
- if ( matcher[ expando ] ) {
- // Find the next relative operator (if any) for proper handling
- j = ++i;
- for ( ; j < len; j++ ) {
- if ( Expr.relative[ tokens[j].type ] ) {
- break;
- }
- }
- return setMatcher(
- i > 1 && elementMatcher( matchers ),
- i > 1 && toSelector(
- // If the preceding token was a descendant combinator, insert an implicit any-element `*`
- tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
- ).replace( rtrim, "$1" ),
- matcher,
- i < j && matcherFromTokens( tokens.slice( i, j ) ),
- j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
- j < len && toSelector( tokens )
- );
- }
- matchers.push( matcher );
- }
- }
-
- return elementMatcher( matchers );
-}
-
-function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
- var bySet = setMatchers.length > 0,
- byElement = elementMatchers.length > 0,
- superMatcher = function( seed, context, xml, results, outermost ) {
- var elem, j, matcher,
- matchedCount = 0,
- i = "0",
- unmatched = seed && [],
- setMatched = [],
- contextBackup = outermostContext,
- // We must always have either seed elements or outermost context
- elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
- // Use integer dirruns iff this is the outermost matcher
- dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
- len = elems.length;
-
- if ( outermost ) {
- outermostContext = context === document || context || outermost;
- }
-
- // Add elements passing elementMatchers directly to results
- // Support: IE<9, Safari
- // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id
- for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
- if ( byElement && elem ) {
- j = 0;
- if ( !context && elem.ownerDocument !== document ) {
- setDocument( elem );
- xml = !documentIsHTML;
- }
- while ( (matcher = elementMatchers[j++]) ) {
- if ( matcher( elem, context || document, xml) ) {
- results.push( elem );
- break;
- }
- }
- if ( outermost ) {
- dirruns = dirrunsUnique;
- }
- }
-
- // Track unmatched elements for set filters
- if ( bySet ) {
- // They will have gone through all possible matchers
- if ( (elem = !matcher && elem) ) {
- matchedCount--;
- }
-
- // Lengthen the array for every element, matched or not
- if ( seed ) {
- unmatched.push( elem );
- }
- }
- }
-
- // `i` is now the count of elements visited above, and adding it to `matchedCount`
- // makes the latter nonnegative.
- matchedCount += i;
-
- // Apply set filters to unmatched elements
- // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
- // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
- // no element matchers and no seed.
- // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
- // case, which will result in a "00" `matchedCount` that differs from `i` but is also
- // numerically zero.
- if ( bySet && i !== matchedCount ) {
- j = 0;
- while ( (matcher = setMatchers[j++]) ) {
- matcher( unmatched, setMatched, context, xml );
- }
-
- if ( seed ) {
- // Reintegrate element matches to eliminate the need for sorting
- if ( matchedCount > 0 ) {
- while ( i-- ) {
- if ( !(unmatched[i] || setMatched[i]) ) {
- setMatched[i] = pop.call( results );
- }
- }
- }
-
- // Discard index placeholder values to get only actual matches
- setMatched = condense( setMatched );
- }
-
- // Add matches to results
- push.apply( results, setMatched );
-
- // Seedless set matches succeeding multiple successful matchers stipulate sorting
- if ( outermost && !seed && setMatched.length > 0 &&
- ( matchedCount + setMatchers.length ) > 1 ) {
-
- Sizzle.uniqueSort( results );
- }
- }
-
- // Override manipulation of globals by nested matchers
- if ( outermost ) {
- dirruns = dirrunsUnique;
- outermostContext = contextBackup;
- }
-
- return unmatched;
- };
-
- return bySet ?
- markFunction( superMatcher ) :
- superMatcher;
-}
-
-compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
- var i,
- setMatchers = [],
- elementMatchers = [],
- cached = compilerCache[ selector + " " ];
-
- if ( !cached ) {
- // Generate a function of recursive functions that can be used to check each element
- if ( !match ) {
- match = tokenize( selector );
- }
- i = match.length;
- while ( i-- ) {
- cached = matcherFromTokens( match[i] );
- if ( cached[ expando ] ) {
- setMatchers.push( cached );
- } else {
- elementMatchers.push( cached );
- }
- }
-
- // Cache the compiled function
- cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
-
- // Save selector and tokenization
- cached.selector = selector;
- }
- return cached;
-};
-
-/**
- * A low-level selection function that works with Sizzle's compiled
- * selector functions
- * @param {String|Function} selector A selector or a pre-compiled
- * selector function built with Sizzle.compile
- * @param {Element} context
- * @param {Array} [results]
- * @param {Array} [seed] A set of elements to match against
- */
-select = Sizzle.select = function( selector, context, results, seed ) {
- var i, tokens, token, type, find,
- compiled = typeof selector === "function" && selector,
- match = !seed && tokenize( (selector = compiled.selector || selector) );
-
- results = results || [];
-
- // Try to minimize operations if there is only one selector in the list and no seed
- // (the latter of which guarantees us context)
- if ( match.length === 1 ) {
-
- // Reduce context if the leading compound selector is an ID
- tokens = match[0] = match[0].slice( 0 );
- if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
- context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {
-
- context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
- if ( !context ) {
- return results;
-
- // Precompiled matchers will still verify ancestry, so step up a level
- } else if ( compiled ) {
- context = context.parentNode;
- }
-
- selector = selector.slice( tokens.shift().value.length );
- }
-
- // Fetch a seed set for right-to-left matching
- i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
- while ( i-- ) {
- token = tokens[i];
-
- // Abort if we hit a combinator
- if ( Expr.relative[ (type = token.type) ] ) {
- break;
- }
- if ( (find = Expr.find[ type ]) ) {
- // Search, expanding context for leading sibling combinators
- if ( (seed = find(
- token.matches[0].replace( runescape, funescape ),
- rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
- )) ) {
-
- // If seed is empty or no tokens remain, we can return early
- tokens.splice( i, 1 );
- selector = seed.length && toSelector( tokens );
- if ( !selector ) {
- push.apply( results, seed );
- return results;
- }
-
- break;
- }
- }
- }
- }
-
- // Compile and execute a filtering function if one is not provided
- // Provide `match` to avoid retokenization if we modified the selector above
- ( compiled || compile( selector, match ) )(
- seed,
- context,
- !documentIsHTML,
- results,
- !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
- );
- return results;
-};
-
-// One-time assignments
-
-// Sort stability
-support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
-
-// Support: Chrome 14-35+
-// Always assume duplicates if they aren't passed to the comparison function
-support.detectDuplicates = !!hasDuplicate;
-
-// Initialize against the default document
-setDocument();
-
-// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
-// Detached nodes confoundingly follow *each other*
-support.sortDetached = assert(function( el ) {
- // Should return 1, but returns 4 (following)
- return el.compareDocumentPosition( document.createElement("fieldset") ) & 1;
-});
-
-// Support: IE<8
-// Prevent attribute/property "interpolation"
-// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
-if ( !assert(function( el ) {
- el.innerHTML = " ";
- return el.firstChild.getAttribute("href") === "#" ;
-}) ) {
- addHandle( "type|href|height|width", function( elem, name, isXML ) {
- if ( !isXML ) {
- return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
- }
- });
-}
-
-// Support: IE<9
-// Use defaultValue in place of getAttribute("value")
-if ( !support.attributes || !assert(function( el ) {
- el.innerHTML = " ";
- el.firstChild.setAttribute( "value", "" );
- return el.firstChild.getAttribute( "value" ) === "";
-}) ) {
- addHandle( "value", function( elem, name, isXML ) {
- if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
- return elem.defaultValue;
- }
- });
-}
-
-// Support: IE<9
-// Use getAttributeNode to fetch booleans when getAttribute lies
-if ( !assert(function( el ) {
- return el.getAttribute("disabled") == null;
-}) ) {
- addHandle( booleans, function( elem, name, isXML ) {
- var val;
- if ( !isXML ) {
- return elem[ name ] === true ? name.toLowerCase() :
- (val = elem.getAttributeNode( name )) && val.specified ?
- val.value :
- null;
- }
- });
-}
-
-return Sizzle;
-
-})( window );
-
-
-
-jQuery.find = Sizzle;
-jQuery.expr = Sizzle.selectors;
-
-// Deprecated
-jQuery.expr[ ":" ] = jQuery.expr.pseudos;
-jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
-jQuery.text = Sizzle.getText;
-jQuery.isXMLDoc = Sizzle.isXML;
-jQuery.contains = Sizzle.contains;
-jQuery.escapeSelector = Sizzle.escape;
-
-
-
-
-var dir = function( elem, dir, until ) {
- var matched = [],
- truncate = until !== undefined;
-
- while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
- if ( elem.nodeType === 1 ) {
- if ( truncate && jQuery( elem ).is( until ) ) {
- break;
- }
- matched.push( elem );
- }
- }
- return matched;
-};
-
-
-var siblings = function( n, elem ) {
- var matched = [];
-
- for ( ; n; n = n.nextSibling ) {
- if ( n.nodeType === 1 && n !== elem ) {
- matched.push( n );
- }
- }
-
- return matched;
-};
-
-
-var rneedsContext = jQuery.expr.match.needsContext;
-
-
-
-function nodeName( elem, name ) {
-
- return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
-
-};
-var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
-
-
-
-// Implement the identical functionality for filter and not
-function winnow( elements, qualifier, not ) {
- if ( isFunction( qualifier ) ) {
- return jQuery.grep( elements, function( elem, i ) {
- return !!qualifier.call( elem, i, elem ) !== not;
- } );
- }
-
- // Single element
- if ( qualifier.nodeType ) {
- return jQuery.grep( elements, function( elem ) {
- return ( elem === qualifier ) !== not;
- } );
- }
-
- // Arraylike of elements (jQuery, arguments, Array)
- if ( typeof qualifier !== "string" ) {
- return jQuery.grep( elements, function( elem ) {
- return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
- } );
- }
-
- // Filtered directly for both simple and complex selectors
- return jQuery.filter( qualifier, elements, not );
-}
-
-jQuery.filter = function( expr, elems, not ) {
- var elem = elems[ 0 ];
-
- if ( not ) {
- expr = ":not(" + expr + ")";
- }
-
- if ( elems.length === 1 && elem.nodeType === 1 ) {
- return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
- }
-
- return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
- return elem.nodeType === 1;
- } ) );
-};
-
-jQuery.fn.extend( {
- find: function( selector ) {
- var i, ret,
- len = this.length,
- self = this;
-
- if ( typeof selector !== "string" ) {
- return this.pushStack( jQuery( selector ).filter( function() {
- for ( i = 0; i < len; i++ ) {
- if ( jQuery.contains( self[ i ], this ) ) {
- return true;
- }
- }
- } ) );
- }
-
- ret = this.pushStack( [] );
-
- for ( i = 0; i < len; i++ ) {
- jQuery.find( selector, self[ i ], ret );
- }
-
- return len > 1 ? jQuery.uniqueSort( ret ) : ret;
- },
- filter: function( selector ) {
- return this.pushStack( winnow( this, selector || [], false ) );
- },
- not: function( selector ) {
- return this.pushStack( winnow( this, selector || [], true ) );
- },
- is: function( selector ) {
- return !!winnow(
- this,
-
- // If this is a positional/relative selector, check membership in the returned set
- // so $("p:first").is("p:last") won't return true for a doc with two "p".
- typeof selector === "string" && rneedsContext.test( selector ) ?
- jQuery( selector ) :
- selector || [],
- false
- ).length;
- }
-} );
-
-
-// Initialize a jQuery object
-
-
-// A central reference to the root jQuery(document)
-var rootjQuery,
-
- // A simple way to check for HTML strings
- // Prioritize #id over to avoid XSS via location.hash (#9521)
- // Strict HTML recognition (#11290: must start with <)
- // Shortcut simple #id case for speed
- rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
-
- init = jQuery.fn.init = function( selector, context, root ) {
- var match, elem;
-
- // HANDLE: $(""), $(null), $(undefined), $(false)
- if ( !selector ) {
- return this;
- }
-
- // Method init() accepts an alternate rootjQuery
- // so migrate can support jQuery.sub (gh-2101)
- root = root || rootjQuery;
-
- // Handle HTML strings
- if ( typeof selector === "string" ) {
- if ( selector[ 0 ] === "<" &&
- selector[ selector.length - 1 ] === ">" &&
- selector.length >= 3 ) {
-
- // Assume that strings that start and end with <> are HTML and skip the regex check
- match = [ null, selector, null ];
-
- } else {
- match = rquickExpr.exec( selector );
- }
-
- // Match html or make sure no context is specified for #id
- if ( match && ( match[ 1 ] || !context ) ) {
-
- // HANDLE: $(html) -> $(array)
- if ( match[ 1 ] ) {
- context = context instanceof jQuery ? context[ 0 ] : context;
-
- // Option to run scripts is true for back-compat
- // Intentionally let the error be thrown if parseHTML is not present
- jQuery.merge( this, jQuery.parseHTML(
- match[ 1 ],
- context && context.nodeType ? context.ownerDocument || context : document,
- true
- ) );
-
- // HANDLE: $(html, props)
- if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
- for ( match in context ) {
-
- // Properties of context are called as methods if possible
- if ( isFunction( this[ match ] ) ) {
- this[ match ]( context[ match ] );
-
- // ...and otherwise set as attributes
- } else {
- this.attr( match, context[ match ] );
- }
- }
- }
-
- return this;
-
- // HANDLE: $(#id)
- } else {
- elem = document.getElementById( match[ 2 ] );
-
- if ( elem ) {
-
- // Inject the element directly into the jQuery object
- this[ 0 ] = elem;
- this.length = 1;
- }
- return this;
- }
-
- // HANDLE: $(expr, $(...))
- } else if ( !context || context.jquery ) {
- return ( context || root ).find( selector );
-
- // HANDLE: $(expr, context)
- // (which is just equivalent to: $(context).find(expr)
- } else {
- return this.constructor( context ).find( selector );
- }
-
- // HANDLE: $(DOMElement)
- } else if ( selector.nodeType ) {
- this[ 0 ] = selector;
- this.length = 1;
- return this;
-
- // HANDLE: $(function)
- // Shortcut for document ready
- } else if ( isFunction( selector ) ) {
- return root.ready !== undefined ?
- root.ready( selector ) :
-
- // Execute immediately if ready is not present
- selector( jQuery );
- }
-
- return jQuery.makeArray( selector, this );
- };
-
-// Give the init function the jQuery prototype for later instantiation
-init.prototype = jQuery.fn;
-
-// Initialize central reference
-rootjQuery = jQuery( document );
-
-
-var rparentsprev = /^(?:parents|prev(?:Until|All))/,
-
- // Methods guaranteed to produce a unique set when starting from a unique set
- guaranteedUnique = {
- children: true,
- contents: true,
- next: true,
- prev: true
- };
-
-jQuery.fn.extend( {
- has: function( target ) {
- var targets = jQuery( target, this ),
- l = targets.length;
-
- return this.filter( function() {
- var i = 0;
- for ( ; i < l; i++ ) {
- if ( jQuery.contains( this, targets[ i ] ) ) {
- return true;
- }
- }
- } );
- },
-
- closest: function( selectors, context ) {
- var cur,
- i = 0,
- l = this.length,
- matched = [],
- targets = typeof selectors !== "string" && jQuery( selectors );
-
- // Positional selectors never match, since there's no _selection_ context
- if ( !rneedsContext.test( selectors ) ) {
- for ( ; i < l; i++ ) {
- for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
-
- // Always skip document fragments
- if ( cur.nodeType < 11 && ( targets ?
- targets.index( cur ) > -1 :
-
- // Don't pass non-elements to Sizzle
- cur.nodeType === 1 &&
- jQuery.find.matchesSelector( cur, selectors ) ) ) {
-
- matched.push( cur );
- break;
- }
- }
- }
- }
-
- return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
- },
-
- // Determine the position of an element within the set
- index: function( elem ) {
-
- // No argument, return index in parent
- if ( !elem ) {
- return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
- }
-
- // Index in selector
- if ( typeof elem === "string" ) {
- return indexOf.call( jQuery( elem ), this[ 0 ] );
- }
-
- // Locate the position of the desired element
- return indexOf.call( this,
-
- // If it receives a jQuery object, the first element is used
- elem.jquery ? elem[ 0 ] : elem
- );
- },
-
- add: function( selector, context ) {
- return this.pushStack(
- jQuery.uniqueSort(
- jQuery.merge( this.get(), jQuery( selector, context ) )
- )
- );
- },
-
- addBack: function( selector ) {
- return this.add( selector == null ?
- this.prevObject : this.prevObject.filter( selector )
- );
- }
-} );
-
-function sibling( cur, dir ) {
- while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
- return cur;
-}
-
-jQuery.each( {
- parent: function( elem ) {
- var parent = elem.parentNode;
- return parent && parent.nodeType !== 11 ? parent : null;
- },
- parents: function( elem ) {
- return dir( elem, "parentNode" );
- },
- parentsUntil: function( elem, i, until ) {
- return dir( elem, "parentNode", until );
- },
- next: function( elem ) {
- return sibling( elem, "nextSibling" );
- },
- prev: function( elem ) {
- return sibling( elem, "previousSibling" );
- },
- nextAll: function( elem ) {
- return dir( elem, "nextSibling" );
- },
- prevAll: function( elem ) {
- return dir( elem, "previousSibling" );
- },
- nextUntil: function( elem, i, until ) {
- return dir( elem, "nextSibling", until );
- },
- prevUntil: function( elem, i, until ) {
- return dir( elem, "previousSibling", until );
- },
- siblings: function( elem ) {
- return siblings( ( elem.parentNode || {} ).firstChild, elem );
- },
- children: function( elem ) {
- return siblings( elem.firstChild );
- },
- contents: function( elem ) {
- if ( typeof elem.contentDocument !== "undefined" ) {
- return elem.contentDocument;
- }
-
- // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
- // Treat the template element as a regular one in browsers that
- // don't support it.
- if ( nodeName( elem, "template" ) ) {
- elem = elem.content || elem;
- }
-
- return jQuery.merge( [], elem.childNodes );
- }
-}, function( name, fn ) {
- jQuery.fn[ name ] = function( until, selector ) {
- var matched = jQuery.map( this, fn, until );
-
- if ( name.slice( -5 ) !== "Until" ) {
- selector = until;
- }
-
- if ( selector && typeof selector === "string" ) {
- matched = jQuery.filter( selector, matched );
- }
-
- if ( this.length > 1 ) {
-
- // Remove duplicates
- if ( !guaranteedUnique[ name ] ) {
- jQuery.uniqueSort( matched );
- }
-
- // Reverse order for parents* and prev-derivatives
- if ( rparentsprev.test( name ) ) {
- matched.reverse();
- }
- }
-
- return this.pushStack( matched );
- };
-} );
-var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
-
-
-
-// Convert String-formatted options into Object-formatted ones
-function createOptions( options ) {
- var object = {};
- jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
- object[ flag ] = true;
- } );
- return object;
-}
-
-/*
- * Create a callback list using the following parameters:
- *
- * options: an optional list of space-separated options that will change how
- * the callback list behaves or a more traditional option object
- *
- * By default a callback list will act like an event callback list and can be
- * "fired" multiple times.
- *
- * Possible options:
- *
- * once: will ensure the callback list can only be fired once (like a Deferred)
- *
- * memory: will keep track of previous values and will call any callback added
- * after the list has been fired right away with the latest "memorized"
- * values (like a Deferred)
- *
- * unique: will ensure a callback can only be added once (no duplicate in the list)
- *
- * stopOnFalse: interrupt callings when a callback returns false
- *
- */
-jQuery.Callbacks = function( options ) {
-
- // Convert options from String-formatted to Object-formatted if needed
- // (we check in cache first)
- options = typeof options === "string" ?
- createOptions( options ) :
- jQuery.extend( {}, options );
-
- var // Flag to know if list is currently firing
- firing,
-
- // Last fire value for non-forgettable lists
- memory,
-
- // Flag to know if list was already fired
- fired,
-
- // Flag to prevent firing
- locked,
-
- // Actual callback list
- list = [],
-
- // Queue of execution data for repeatable lists
- queue = [],
-
- // Index of currently firing callback (modified by add/remove as needed)
- firingIndex = -1,
-
- // Fire callbacks
- fire = function() {
-
- // Enforce single-firing
- locked = locked || options.once;
-
- // Execute callbacks for all pending executions,
- // respecting firingIndex overrides and runtime changes
- fired = firing = true;
- for ( ; queue.length; firingIndex = -1 ) {
- memory = queue.shift();
- while ( ++firingIndex < list.length ) {
-
- // Run callback and check for early termination
- if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
- options.stopOnFalse ) {
-
- // Jump to end and forget the data so .add doesn't re-fire
- firingIndex = list.length;
- memory = false;
- }
- }
- }
-
- // Forget the data if we're done with it
- if ( !options.memory ) {
- memory = false;
- }
-
- firing = false;
-
- // Clean up if we're done firing for good
- if ( locked ) {
-
- // Keep an empty list if we have data for future add calls
- if ( memory ) {
- list = [];
-
- // Otherwise, this object is spent
- } else {
- list = "";
- }
- }
- },
-
- // Actual Callbacks object
- self = {
-
- // Add a callback or a collection of callbacks to the list
- add: function() {
- if ( list ) {
-
- // If we have memory from a past run, we should fire after adding
- if ( memory && !firing ) {
- firingIndex = list.length - 1;
- queue.push( memory );
- }
-
- ( function add( args ) {
- jQuery.each( args, function( _, arg ) {
- if ( isFunction( arg ) ) {
- if ( !options.unique || !self.has( arg ) ) {
- list.push( arg );
- }
- } else if ( arg && arg.length && toType( arg ) !== "string" ) {
-
- // Inspect recursively
- add( arg );
- }
- } );
- } )( arguments );
-
- if ( memory && !firing ) {
- fire();
- }
- }
- return this;
- },
-
- // Remove a callback from the list
- remove: function() {
- jQuery.each( arguments, function( _, arg ) {
- var index;
- while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
- list.splice( index, 1 );
-
- // Handle firing indexes
- if ( index <= firingIndex ) {
- firingIndex--;
- }
- }
- } );
- return this;
- },
-
- // Check if a given callback is in the list.
- // If no argument is given, return whether or not list has callbacks attached.
- has: function( fn ) {
- return fn ?
- jQuery.inArray( fn, list ) > -1 :
- list.length > 0;
- },
-
- // Remove all callbacks from the list
- empty: function() {
- if ( list ) {
- list = [];
- }
- return this;
- },
-
- // Disable .fire and .add
- // Abort any current/pending executions
- // Clear all callbacks and values
- disable: function() {
- locked = queue = [];
- list = memory = "";
- return this;
- },
- disabled: function() {
- return !list;
- },
-
- // Disable .fire
- // Also disable .add unless we have memory (since it would have no effect)
- // Abort any pending executions
- lock: function() {
- locked = queue = [];
- if ( !memory && !firing ) {
- list = memory = "";
- }
- return this;
- },
- locked: function() {
- return !!locked;
- },
-
- // Call all callbacks with the given context and arguments
- fireWith: function( context, args ) {
- if ( !locked ) {
- args = args || [];
- args = [ context, args.slice ? args.slice() : args ];
- queue.push( args );
- if ( !firing ) {
- fire();
- }
- }
- return this;
- },
-
- // Call all the callbacks with the given arguments
- fire: function() {
- self.fireWith( this, arguments );
- return this;
- },
-
- // To know if the callbacks have already been called at least once
- fired: function() {
- return !!fired;
- }
- };
-
- return self;
-};
-
-
-function Identity( v ) {
- return v;
-}
-function Thrower( ex ) {
- throw ex;
-}
-
-function adoptValue( value, resolve, reject, noValue ) {
- var method;
-
- try {
-
- // Check for promise aspect first to privilege synchronous behavior
- if ( value && isFunction( ( method = value.promise ) ) ) {
- method.call( value ).done( resolve ).fail( reject );
-
- // Other thenables
- } else if ( value && isFunction( ( method = value.then ) ) ) {
- method.call( value, resolve, reject );
-
- // Other non-thenables
- } else {
-
- // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
- // * false: [ value ].slice( 0 ) => resolve( value )
- // * true: [ value ].slice( 1 ) => resolve()
- resolve.apply( undefined, [ value ].slice( noValue ) );
- }
-
- // For Promises/A+, convert exceptions into rejections
- // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
- // Deferred#then to conditionally suppress rejection.
- } catch ( value ) {
-
- // Support: Android 4.0 only
- // Strict mode functions invoked without .call/.apply get global-object context
- reject.apply( undefined, [ value ] );
- }
-}
-
-jQuery.extend( {
-
- Deferred: function( func ) {
- var tuples = [
-
- // action, add listener, callbacks,
- // ... .then handlers, argument index, [final state]
- [ "notify", "progress", jQuery.Callbacks( "memory" ),
- jQuery.Callbacks( "memory" ), 2 ],
- [ "resolve", "done", jQuery.Callbacks( "once memory" ),
- jQuery.Callbacks( "once memory" ), 0, "resolved" ],
- [ "reject", "fail", jQuery.Callbacks( "once memory" ),
- jQuery.Callbacks( "once memory" ), 1, "rejected" ]
- ],
- state = "pending",
- promise = {
- state: function() {
- return state;
- },
- always: function() {
- deferred.done( arguments ).fail( arguments );
- return this;
- },
- "catch": function( fn ) {
- return promise.then( null, fn );
- },
-
- // Keep pipe for back-compat
- pipe: function( /* fnDone, fnFail, fnProgress */ ) {
- var fns = arguments;
-
- return jQuery.Deferred( function( newDefer ) {
- jQuery.each( tuples, function( i, tuple ) {
-
- // Map tuples (progress, done, fail) to arguments (done, fail, progress)
- var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
-
- // deferred.progress(function() { bind to newDefer or newDefer.notify })
- // deferred.done(function() { bind to newDefer or newDefer.resolve })
- // deferred.fail(function() { bind to newDefer or newDefer.reject })
- deferred[ tuple[ 1 ] ]( function() {
- var returned = fn && fn.apply( this, arguments );
- if ( returned && isFunction( returned.promise ) ) {
- returned.promise()
- .progress( newDefer.notify )
- .done( newDefer.resolve )
- .fail( newDefer.reject );
- } else {
- newDefer[ tuple[ 0 ] + "With" ](
- this,
- fn ? [ returned ] : arguments
- );
- }
- } );
- } );
- fns = null;
- } ).promise();
- },
- then: function( onFulfilled, onRejected, onProgress ) {
- var maxDepth = 0;
- function resolve( depth, deferred, handler, special ) {
- return function() {
- var that = this,
- args = arguments,
- mightThrow = function() {
- var returned, then;
-
- // Support: Promises/A+ section 2.3.3.3.3
- // https://promisesaplus.com/#point-59
- // Ignore double-resolution attempts
- if ( depth < maxDepth ) {
- return;
- }
-
- returned = handler.apply( that, args );
-
- // Support: Promises/A+ section 2.3.1
- // https://promisesaplus.com/#point-48
- if ( returned === deferred.promise() ) {
- throw new TypeError( "Thenable self-resolution" );
- }
-
- // Support: Promises/A+ sections 2.3.3.1, 3.5
- // https://promisesaplus.com/#point-54
- // https://promisesaplus.com/#point-75
- // Retrieve `then` only once
- then = returned &&
-
- // Support: Promises/A+ section 2.3.4
- // https://promisesaplus.com/#point-64
- // Only check objects and functions for thenability
- ( typeof returned === "object" ||
- typeof returned === "function" ) &&
- returned.then;
-
- // Handle a returned thenable
- if ( isFunction( then ) ) {
-
- // Special processors (notify) just wait for resolution
- if ( special ) {
- then.call(
- returned,
- resolve( maxDepth, deferred, Identity, special ),
- resolve( maxDepth, deferred, Thrower, special )
- );
-
- // Normal processors (resolve) also hook into progress
- } else {
-
- // ...and disregard older resolution values
- maxDepth++;
-
- then.call(
- returned,
- resolve( maxDepth, deferred, Identity, special ),
- resolve( maxDepth, deferred, Thrower, special ),
- resolve( maxDepth, deferred, Identity,
- deferred.notifyWith )
- );
- }
-
- // Handle all other returned values
- } else {
-
- // Only substitute handlers pass on context
- // and multiple values (non-spec behavior)
- if ( handler !== Identity ) {
- that = undefined;
- args = [ returned ];
- }
-
- // Process the value(s)
- // Default process is resolve
- ( special || deferred.resolveWith )( that, args );
- }
- },
-
- // Only normal processors (resolve) catch and reject exceptions
- process = special ?
- mightThrow :
- function() {
- try {
- mightThrow();
- } catch ( e ) {
-
- if ( jQuery.Deferred.exceptionHook ) {
- jQuery.Deferred.exceptionHook( e,
- process.stackTrace );
- }
-
- // Support: Promises/A+ section 2.3.3.3.4.1
- // https://promisesaplus.com/#point-61
- // Ignore post-resolution exceptions
- if ( depth + 1 >= maxDepth ) {
-
- // Only substitute handlers pass on context
- // and multiple values (non-spec behavior)
- if ( handler !== Thrower ) {
- that = undefined;
- args = [ e ];
- }
-
- deferred.rejectWith( that, args );
- }
- }
- };
-
- // Support: Promises/A+ section 2.3.3.3.1
- // https://promisesaplus.com/#point-57
- // Re-resolve promises immediately to dodge false rejection from
- // subsequent errors
- if ( depth ) {
- process();
- } else {
-
- // Call an optional hook to record the stack, in case of exception
- // since it's otherwise lost when execution goes async
- if ( jQuery.Deferred.getStackHook ) {
- process.stackTrace = jQuery.Deferred.getStackHook();
- }
- window.setTimeout( process );
- }
- };
- }
-
- return jQuery.Deferred( function( newDefer ) {
-
- // progress_handlers.add( ... )
- tuples[ 0 ][ 3 ].add(
- resolve(
- 0,
- newDefer,
- isFunction( onProgress ) ?
- onProgress :
- Identity,
- newDefer.notifyWith
- )
- );
-
- // fulfilled_handlers.add( ... )
- tuples[ 1 ][ 3 ].add(
- resolve(
- 0,
- newDefer,
- isFunction( onFulfilled ) ?
- onFulfilled :
- Identity
- )
- );
-
- // rejected_handlers.add( ... )
- tuples[ 2 ][ 3 ].add(
- resolve(
- 0,
- newDefer,
- isFunction( onRejected ) ?
- onRejected :
- Thrower
- )
- );
- } ).promise();
- },
-
- // Get a promise for this deferred
- // If obj is provided, the promise aspect is added to the object
- promise: function( obj ) {
- return obj != null ? jQuery.extend( obj, promise ) : promise;
- }
- },
- deferred = {};
-
- // Add list-specific methods
- jQuery.each( tuples, function( i, tuple ) {
- var list = tuple[ 2 ],
- stateString = tuple[ 5 ];
-
- // promise.progress = list.add
- // promise.done = list.add
- // promise.fail = list.add
- promise[ tuple[ 1 ] ] = list.add;
-
- // Handle state
- if ( stateString ) {
- list.add(
- function() {
-
- // state = "resolved" (i.e., fulfilled)
- // state = "rejected"
- state = stateString;
- },
-
- // rejected_callbacks.disable
- // fulfilled_callbacks.disable
- tuples[ 3 - i ][ 2 ].disable,
-
- // rejected_handlers.disable
- // fulfilled_handlers.disable
- tuples[ 3 - i ][ 3 ].disable,
-
- // progress_callbacks.lock
- tuples[ 0 ][ 2 ].lock,
-
- // progress_handlers.lock
- tuples[ 0 ][ 3 ].lock
- );
- }
-
- // progress_handlers.fire
- // fulfilled_handlers.fire
- // rejected_handlers.fire
- list.add( tuple[ 3 ].fire );
-
- // deferred.notify = function() { deferred.notifyWith(...) }
- // deferred.resolve = function() { deferred.resolveWith(...) }
- // deferred.reject = function() { deferred.rejectWith(...) }
- deferred[ tuple[ 0 ] ] = function() {
- deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
- return this;
- };
-
- // deferred.notifyWith = list.fireWith
- // deferred.resolveWith = list.fireWith
- // deferred.rejectWith = list.fireWith
- deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
- } );
-
- // Make the deferred a promise
- promise.promise( deferred );
-
- // Call given func if any
- if ( func ) {
- func.call( deferred, deferred );
- }
-
- // All done!
- return deferred;
- },
-
- // Deferred helper
- when: function( singleValue ) {
- var
-
- // count of uncompleted subordinates
- remaining = arguments.length,
-
- // count of unprocessed arguments
- i = remaining,
-
- // subordinate fulfillment data
- resolveContexts = Array( i ),
- resolveValues = slice.call( arguments ),
-
- // the master Deferred
- master = jQuery.Deferred(),
-
- // subordinate callback factory
- updateFunc = function( i ) {
- return function( value ) {
- resolveContexts[ i ] = this;
- resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
- if ( !( --remaining ) ) {
- master.resolveWith( resolveContexts, resolveValues );
- }
- };
- };
-
- // Single- and empty arguments are adopted like Promise.resolve
- if ( remaining <= 1 ) {
- adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
- !remaining );
-
- // Use .then() to unwrap secondary thenables (cf. gh-3000)
- if ( master.state() === "pending" ||
- isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
-
- return master.then();
- }
- }
-
- // Multiple arguments are aggregated like Promise.all array elements
- while ( i-- ) {
- adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
- }
-
- return master.promise();
- }
-} );
-
-
-// These usually indicate a programmer mistake during development,
-// warn about them ASAP rather than swallowing them by default.
-var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
-
-jQuery.Deferred.exceptionHook = function( error, stack ) {
-
- // Support: IE 8 - 9 only
- // Console exists when dev tools are open, which can happen at any time
- if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
- window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
- }
-};
-
-
-
-
-jQuery.readyException = function( error ) {
- window.setTimeout( function() {
- throw error;
- } );
-};
-
-
-
-
-// The deferred used on DOM ready
-var readyList = jQuery.Deferred();
-
-jQuery.fn.ready = function( fn ) {
-
- readyList
- .then( fn )
-
- // Wrap jQuery.readyException in a function so that the lookup
- // happens at the time of error handling instead of callback
- // registration.
- .catch( function( error ) {
- jQuery.readyException( error );
- } );
-
- return this;
-};
-
-jQuery.extend( {
-
- // Is the DOM ready to be used? Set to true once it occurs.
- isReady: false,
-
- // A counter to track how many items to wait for before
- // the ready event fires. See #6781
- readyWait: 1,
-
- // Handle when the DOM is ready
- ready: function( wait ) {
-
- // Abort if there are pending holds or we're already ready
- if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
- return;
- }
-
- // Remember that the DOM is ready
- jQuery.isReady = true;
-
- // If a normal DOM Ready event fired, decrement, and wait if need be
- if ( wait !== true && --jQuery.readyWait > 0 ) {
- return;
- }
-
- // If there are functions bound, to execute
- readyList.resolveWith( document, [ jQuery ] );
- }
-} );
-
-jQuery.ready.then = readyList.then;
-
-// The ready event handler and self cleanup method
-function completed() {
- document.removeEventListener( "DOMContentLoaded", completed );
- window.removeEventListener( "load", completed );
- jQuery.ready();
-}
-
-// Catch cases where $(document).ready() is called
-// after the browser event has already occurred.
-// Support: IE <=9 - 10 only
-// Older IE sometimes signals "interactive" too soon
-if ( document.readyState === "complete" ||
- ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
-
- // Handle it asynchronously to allow scripts the opportunity to delay ready
- window.setTimeout( jQuery.ready );
-
-} else {
-
- // Use the handy event callback
- document.addEventListener( "DOMContentLoaded", completed );
-
- // A fallback to window.onload, that will always work
- window.addEventListener( "load", completed );
-}
-
-
-
-
-// Multifunctional method to get and set values of a collection
-// The value/s can optionally be executed if it's a function
-var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
- var i = 0,
- len = elems.length,
- bulk = key == null;
-
- // Sets many values
- if ( toType( key ) === "object" ) {
- chainable = true;
- for ( i in key ) {
- access( elems, fn, i, key[ i ], true, emptyGet, raw );
- }
-
- // Sets one value
- } else if ( value !== undefined ) {
- chainable = true;
-
- if ( !isFunction( value ) ) {
- raw = true;
- }
-
- if ( bulk ) {
-
- // Bulk operations run against the entire set
- if ( raw ) {
- fn.call( elems, value );
- fn = null;
-
- // ...except when executing function values
- } else {
- bulk = fn;
- fn = function( elem, key, value ) {
- return bulk.call( jQuery( elem ), value );
- };
- }
- }
-
- if ( fn ) {
- for ( ; i < len; i++ ) {
- fn(
- elems[ i ], key, raw ?
- value :
- value.call( elems[ i ], i, fn( elems[ i ], key ) )
- );
- }
- }
- }
-
- if ( chainable ) {
- return elems;
- }
-
- // Gets
- if ( bulk ) {
- return fn.call( elems );
- }
-
- return len ? fn( elems[ 0 ], key ) : emptyGet;
-};
-
-
-// Matches dashed string for camelizing
-var rmsPrefix = /^-ms-/,
- rdashAlpha = /-([a-z])/g;
-
-// Used by camelCase as callback to replace()
-function fcamelCase( all, letter ) {
- return letter.toUpperCase();
-}
-
-// Convert dashed to camelCase; used by the css and data modules
-// Support: IE <=9 - 11, Edge 12 - 15
-// Microsoft forgot to hump their vendor prefix (#9572)
-function camelCase( string ) {
- return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
-}
-var acceptData = function( owner ) {
-
- // Accepts only:
- // - Node
- // - Node.ELEMENT_NODE
- // - Node.DOCUMENT_NODE
- // - Object
- // - Any
- return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
-};
-
-
-
-
-function Data() {
- this.expando = jQuery.expando + Data.uid++;
-}
-
-Data.uid = 1;
-
-Data.prototype = {
-
- cache: function( owner ) {
-
- // Check if the owner object already has a cache
- var value = owner[ this.expando ];
-
- // If not, create one
- if ( !value ) {
- value = {};
-
- // We can accept data for non-element nodes in modern browsers,
- // but we should not, see #8335.
- // Always return an empty object.
- if ( acceptData( owner ) ) {
-
- // If it is a node unlikely to be stringify-ed or looped over
- // use plain assignment
- if ( owner.nodeType ) {
- owner[ this.expando ] = value;
-
- // Otherwise secure it in a non-enumerable property
- // configurable must be true to allow the property to be
- // deleted when data is removed
- } else {
- Object.defineProperty( owner, this.expando, {
- value: value,
- configurable: true
- } );
- }
- }
- }
-
- return value;
- },
- set: function( owner, data, value ) {
- var prop,
- cache = this.cache( owner );
-
- // Handle: [ owner, key, value ] args
- // Always use camelCase key (gh-2257)
- if ( typeof data === "string" ) {
- cache[ camelCase( data ) ] = value;
-
- // Handle: [ owner, { properties } ] args
- } else {
-
- // Copy the properties one-by-one to the cache object
- for ( prop in data ) {
- cache[ camelCase( prop ) ] = data[ prop ];
- }
- }
- return cache;
- },
- get: function( owner, key ) {
- return key === undefined ?
- this.cache( owner ) :
-
- // Always use camelCase key (gh-2257)
- owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
- },
- access: function( owner, key, value ) {
-
- // In cases where either:
- //
- // 1. No key was specified
- // 2. A string key was specified, but no value provided
- //
- // Take the "read" path and allow the get method to determine
- // which value to return, respectively either:
- //
- // 1. The entire cache object
- // 2. The data stored at the key
- //
- if ( key === undefined ||
- ( ( key && typeof key === "string" ) && value === undefined ) ) {
-
- return this.get( owner, key );
- }
-
- // When the key is not a string, or both a key and value
- // are specified, set or extend (existing objects) with either:
- //
- // 1. An object of properties
- // 2. A key and value
- //
- this.set( owner, key, value );
-
- // Since the "set" path can have two possible entry points
- // return the expected data based on which path was taken[*]
- return value !== undefined ? value : key;
- },
- remove: function( owner, key ) {
- var i,
- cache = owner[ this.expando ];
-
- if ( cache === undefined ) {
- return;
- }
-
- if ( key !== undefined ) {
-
- // Support array or space separated string of keys
- if ( Array.isArray( key ) ) {
-
- // If key is an array of keys...
- // We always set camelCase keys, so remove that.
- key = key.map( camelCase );
- } else {
- key = camelCase( key );
-
- // If a key with the spaces exists, use it.
- // Otherwise, create an array by matching non-whitespace
- key = key in cache ?
- [ key ] :
- ( key.match( rnothtmlwhite ) || [] );
- }
-
- i = key.length;
-
- while ( i-- ) {
- delete cache[ key[ i ] ];
- }
- }
-
- // Remove the expando if there's no more data
- if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
-
- // Support: Chrome <=35 - 45
- // Webkit & Blink performance suffers when deleting properties
- // from DOM nodes, so set to undefined instead
- // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
- if ( owner.nodeType ) {
- owner[ this.expando ] = undefined;
- } else {
- delete owner[ this.expando ];
- }
- }
- },
- hasData: function( owner ) {
- var cache = owner[ this.expando ];
- return cache !== undefined && !jQuery.isEmptyObject( cache );
- }
-};
-var dataPriv = new Data();
-
-var dataUser = new Data();
-
-
-
-// Implementation Summary
-//
-// 1. Enforce API surface and semantic compatibility with 1.9.x branch
-// 2. Improve the module's maintainability by reducing the storage
-// paths to a single mechanism.
-// 3. Use the same single mechanism to support "private" and "user" data.
-// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
-// 5. Avoid exposing implementation details on user objects (eg. expando properties)
-// 6. Provide a clear path for implementation upgrade to WeakMap in 2014
-
-var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
- rmultiDash = /[A-Z]/g;
-
-function getData( data ) {
- if ( data === "true" ) {
- return true;
- }
-
- if ( data === "false" ) {
- return false;
- }
-
- if ( data === "null" ) {
- return null;
- }
-
- // Only convert to a number if it doesn't change the string
- if ( data === +data + "" ) {
- return +data;
- }
-
- if ( rbrace.test( data ) ) {
- return JSON.parse( data );
- }
-
- return data;
-}
-
-function dataAttr( elem, key, data ) {
- var name;
-
- // If nothing was found internally, try to fetch any
- // data from the HTML5 data-* attribute
- if ( data === undefined && elem.nodeType === 1 ) {
- name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
- data = elem.getAttribute( name );
-
- if ( typeof data === "string" ) {
- try {
- data = getData( data );
- } catch ( e ) {}
-
- // Make sure we set the data so it isn't changed later
- dataUser.set( elem, key, data );
- } else {
- data = undefined;
- }
- }
- return data;
-}
-
-jQuery.extend( {
- hasData: function( elem ) {
- return dataUser.hasData( elem ) || dataPriv.hasData( elem );
- },
-
- data: function( elem, name, data ) {
- return dataUser.access( elem, name, data );
- },
-
- removeData: function( elem, name ) {
- dataUser.remove( elem, name );
- },
-
- // TODO: Now that all calls to _data and _removeData have been replaced
- // with direct calls to dataPriv methods, these can be deprecated.
- _data: function( elem, name, data ) {
- return dataPriv.access( elem, name, data );
- },
-
- _removeData: function( elem, name ) {
- dataPriv.remove( elem, name );
- }
-} );
-
-jQuery.fn.extend( {
- data: function( key, value ) {
- var i, name, data,
- elem = this[ 0 ],
- attrs = elem && elem.attributes;
-
- // Gets all values
- if ( key === undefined ) {
- if ( this.length ) {
- data = dataUser.get( elem );
-
- if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
- i = attrs.length;
- while ( i-- ) {
-
- // Support: IE 11 only
- // The attrs elements can be null (#14894)
- if ( attrs[ i ] ) {
- name = attrs[ i ].name;
- if ( name.indexOf( "data-" ) === 0 ) {
- name = camelCase( name.slice( 5 ) );
- dataAttr( elem, name, data[ name ] );
- }
- }
- }
- dataPriv.set( elem, "hasDataAttrs", true );
- }
- }
-
- return data;
- }
-
- // Sets multiple values
- if ( typeof key === "object" ) {
- return this.each( function() {
- dataUser.set( this, key );
- } );
- }
-
- return access( this, function( value ) {
- var data;
-
- // The calling jQuery object (element matches) is not empty
- // (and therefore has an element appears at this[ 0 ]) and the
- // `value` parameter was not undefined. An empty jQuery object
- // will result in `undefined` for elem = this[ 0 ] which will
- // throw an exception if an attempt to read a data cache is made.
- if ( elem && value === undefined ) {
-
- // Attempt to get data from the cache
- // The key will always be camelCased in Data
- data = dataUser.get( elem, key );
- if ( data !== undefined ) {
- return data;
- }
-
- // Attempt to "discover" the data in
- // HTML5 custom data-* attrs
- data = dataAttr( elem, key );
- if ( data !== undefined ) {
- return data;
- }
-
- // We tried really hard, but the data doesn't exist.
- return;
- }
-
- // Set the data...
- this.each( function() {
-
- // We always store the camelCased key
- dataUser.set( this, key, value );
- } );
- }, null, value, arguments.length > 1, null, true );
- },
-
- removeData: function( key ) {
- return this.each( function() {
- dataUser.remove( this, key );
- } );
- }
-} );
-
-
-jQuery.extend( {
- queue: function( elem, type, data ) {
- var queue;
-
- if ( elem ) {
- type = ( type || "fx" ) + "queue";
- queue = dataPriv.get( elem, type );
-
- // Speed up dequeue by getting out quickly if this is just a lookup
- if ( data ) {
- if ( !queue || Array.isArray( data ) ) {
- queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
- } else {
- queue.push( data );
- }
- }
- return queue || [];
- }
- },
-
- dequeue: function( elem, type ) {
- type = type || "fx";
-
- var queue = jQuery.queue( elem, type ),
- startLength = queue.length,
- fn = queue.shift(),
- hooks = jQuery._queueHooks( elem, type ),
- next = function() {
- jQuery.dequeue( elem, type );
- };
-
- // If the fx queue is dequeued, always remove the progress sentinel
- if ( fn === "inprogress" ) {
- fn = queue.shift();
- startLength--;
- }
-
- if ( fn ) {
-
- // Add a progress sentinel to prevent the fx queue from being
- // automatically dequeued
- if ( type === "fx" ) {
- queue.unshift( "inprogress" );
- }
-
- // Clear up the last queue stop function
- delete hooks.stop;
- fn.call( elem, next, hooks );
- }
-
- if ( !startLength && hooks ) {
- hooks.empty.fire();
- }
- },
-
- // Not public - generate a queueHooks object, or return the current one
- _queueHooks: function( elem, type ) {
- var key = type + "queueHooks";
- return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
- empty: jQuery.Callbacks( "once memory" ).add( function() {
- dataPriv.remove( elem, [ type + "queue", key ] );
- } )
- } );
- }
-} );
-
-jQuery.fn.extend( {
- queue: function( type, data ) {
- var setter = 2;
-
- if ( typeof type !== "string" ) {
- data = type;
- type = "fx";
- setter--;
- }
-
- if ( arguments.length < setter ) {
- return jQuery.queue( this[ 0 ], type );
- }
-
- return data === undefined ?
- this :
- this.each( function() {
- var queue = jQuery.queue( this, type, data );
-
- // Ensure a hooks for this queue
- jQuery._queueHooks( this, type );
-
- if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
- jQuery.dequeue( this, type );
- }
- } );
- },
- dequeue: function( type ) {
- return this.each( function() {
- jQuery.dequeue( this, type );
- } );
- },
- clearQueue: function( type ) {
- return this.queue( type || "fx", [] );
- },
-
- // Get a promise resolved when queues of a certain type
- // are emptied (fx is the type by default)
- promise: function( type, obj ) {
- var tmp,
- count = 1,
- defer = jQuery.Deferred(),
- elements = this,
- i = this.length,
- resolve = function() {
- if ( !( --count ) ) {
- defer.resolveWith( elements, [ elements ] );
- }
- };
-
- if ( typeof type !== "string" ) {
- obj = type;
- type = undefined;
- }
- type = type || "fx";
-
- while ( i-- ) {
- tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
- if ( tmp && tmp.empty ) {
- count++;
- tmp.empty.add( resolve );
- }
- }
- resolve();
- return defer.promise( obj );
- }
-} );
-var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
-
-var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
-
-
-var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
-
-var documentElement = document.documentElement;
-
-
-
- var isAttached = function( elem ) {
- return jQuery.contains( elem.ownerDocument, elem );
- },
- composed = { composed: true };
-
- // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only
- // Check attachment across shadow DOM boundaries when possible (gh-3504)
- // Support: iOS 10.0-10.2 only
- // Early iOS 10 versions support `attachShadow` but not `getRootNode`,
- // leading to errors. We need to check for `getRootNode`.
- if ( documentElement.getRootNode ) {
- isAttached = function( elem ) {
- return jQuery.contains( elem.ownerDocument, elem ) ||
- elem.getRootNode( composed ) === elem.ownerDocument;
- };
- }
-var isHiddenWithinTree = function( elem, el ) {
-
- // isHiddenWithinTree might be called from jQuery#filter function;
- // in that case, element will be second argument
- elem = el || elem;
-
- // Inline style trumps all
- return elem.style.display === "none" ||
- elem.style.display === "" &&
-
- // Otherwise, check computed style
- // Support: Firefox <=43 - 45
- // Disconnected elements can have computed display: none, so first confirm that elem is
- // in the document.
- isAttached( elem ) &&
-
- jQuery.css( elem, "display" ) === "none";
- };
-
-var swap = function( elem, options, callback, args ) {
- var ret, name,
- old = {};
-
- // Remember the old values, and insert the new ones
- for ( name in options ) {
- old[ name ] = elem.style[ name ];
- elem.style[ name ] = options[ name ];
- }
-
- ret = callback.apply( elem, args || [] );
-
- // Revert the old values
- for ( name in options ) {
- elem.style[ name ] = old[ name ];
- }
-
- return ret;
-};
-
-
-
-
-function adjustCSS( elem, prop, valueParts, tween ) {
- var adjusted, scale,
- maxIterations = 20,
- currentValue = tween ?
- function() {
- return tween.cur();
- } :
- function() {
- return jQuery.css( elem, prop, "" );
- },
- initial = currentValue(),
- unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
-
- // Starting value computation is required for potential unit mismatches
- initialInUnit = elem.nodeType &&
- ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
- rcssNum.exec( jQuery.css( elem, prop ) );
-
- if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
-
- // Support: Firefox <=54
- // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)
- initial = initial / 2;
-
- // Trust units reported by jQuery.css
- unit = unit || initialInUnit[ 3 ];
-
- // Iteratively approximate from a nonzero starting point
- initialInUnit = +initial || 1;
-
- while ( maxIterations-- ) {
-
- // Evaluate and update our best guess (doubling guesses that zero out).
- // Finish if the scale equals or crosses 1 (making the old*new product non-positive).
- jQuery.style( elem, prop, initialInUnit + unit );
- if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {
- maxIterations = 0;
- }
- initialInUnit = initialInUnit / scale;
-
- }
-
- initialInUnit = initialInUnit * 2;
- jQuery.style( elem, prop, initialInUnit + unit );
-
- // Make sure we update the tween properties later on
- valueParts = valueParts || [];
- }
-
- if ( valueParts ) {
- initialInUnit = +initialInUnit || +initial || 0;
-
- // Apply relative offset (+=/-=) if specified
- adjusted = valueParts[ 1 ] ?
- initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
- +valueParts[ 2 ];
- if ( tween ) {
- tween.unit = unit;
- tween.start = initialInUnit;
- tween.end = adjusted;
- }
- }
- return adjusted;
-}
-
-
-var defaultDisplayMap = {};
-
-function getDefaultDisplay( elem ) {
- var temp,
- doc = elem.ownerDocument,
- nodeName = elem.nodeName,
- display = defaultDisplayMap[ nodeName ];
-
- if ( display ) {
- return display;
- }
-
- temp = doc.body.appendChild( doc.createElement( nodeName ) );
- display = jQuery.css( temp, "display" );
-
- temp.parentNode.removeChild( temp );
-
- if ( display === "none" ) {
- display = "block";
- }
- defaultDisplayMap[ nodeName ] = display;
-
- return display;
-}
-
-function showHide( elements, show ) {
- var display, elem,
- values = [],
- index = 0,
- length = elements.length;
-
- // Determine new display value for elements that need to change
- for ( ; index < length; index++ ) {
- elem = elements[ index ];
- if ( !elem.style ) {
- continue;
- }
-
- display = elem.style.display;
- if ( show ) {
-
- // Since we force visibility upon cascade-hidden elements, an immediate (and slow)
- // check is required in this first loop unless we have a nonempty display value (either
- // inline or about-to-be-restored)
- if ( display === "none" ) {
- values[ index ] = dataPriv.get( elem, "display" ) || null;
- if ( !values[ index ] ) {
- elem.style.display = "";
- }
- }
- if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
- values[ index ] = getDefaultDisplay( elem );
- }
- } else {
- if ( display !== "none" ) {
- values[ index ] = "none";
-
- // Remember what we're overwriting
- dataPriv.set( elem, "display", display );
- }
- }
- }
-
- // Set the display of the elements in a second loop to avoid constant reflow
- for ( index = 0; index < length; index++ ) {
- if ( values[ index ] != null ) {
- elements[ index ].style.display = values[ index ];
- }
- }
-
- return elements;
-}
-
-jQuery.fn.extend( {
- show: function() {
- return showHide( this, true );
- },
- hide: function() {
- return showHide( this );
- },
- toggle: function( state ) {
- if ( typeof state === "boolean" ) {
- return state ? this.show() : this.hide();
- }
-
- return this.each( function() {
- if ( isHiddenWithinTree( this ) ) {
- jQuery( this ).show();
- } else {
- jQuery( this ).hide();
- }
- } );
- }
-} );
-var rcheckableType = ( /^(?:checkbox|radio)$/i );
-
-var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i );
-
-var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i );
-
-
-
-// We have to close these tags to support XHTML (#13200)
-var wrapMap = {
-
- // Support: IE <=9 only
- option: [ 1, "", " " ],
-
- // XHTML parsers do not magically insert elements in the
- // same way that tag soup parsers do. So we cannot shorten
- // this by omitting or other required elements.
- thead: [ 1, "" ],
- col: [ 2, "" ],
- tr: [ 2, "" ],
- td: [ 3, "" ],
-
- _default: [ 0, "", "" ]
-};
-
-// Support: IE <=9 only
-wrapMap.optgroup = wrapMap.option;
-
-wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
-wrapMap.th = wrapMap.td;
-
-
-function getAll( context, tag ) {
-
- // Support: IE <=9 - 11 only
- // Use typeof to avoid zero-argument method invocation on host objects (#15151)
- var ret;
-
- if ( typeof context.getElementsByTagName !== "undefined" ) {
- ret = context.getElementsByTagName( tag || "*" );
-
- } else if ( typeof context.querySelectorAll !== "undefined" ) {
- ret = context.querySelectorAll( tag || "*" );
-
- } else {
- ret = [];
- }
-
- if ( tag === undefined || tag && nodeName( context, tag ) ) {
- return jQuery.merge( [ context ], ret );
- }
-
- return ret;
-}
-
-
-// Mark scripts as having already been evaluated
-function setGlobalEval( elems, refElements ) {
- var i = 0,
- l = elems.length;
-
- for ( ; i < l; i++ ) {
- dataPriv.set(
- elems[ i ],
- "globalEval",
- !refElements || dataPriv.get( refElements[ i ], "globalEval" )
- );
- }
-}
-
-
-var rhtml = /<|?\w+;/;
-
-function buildFragment( elems, context, scripts, selection, ignored ) {
- var elem, tmp, tag, wrap, attached, j,
- fragment = context.createDocumentFragment(),
- nodes = [],
- i = 0,
- l = elems.length;
-
- for ( ; i < l; i++ ) {
- elem = elems[ i ];
-
- if ( elem || elem === 0 ) {
-
- // Add nodes directly
- if ( toType( elem ) === "object" ) {
-
- // Support: Android <=4.0 only, PhantomJS 1 only
- // push.apply(_, arraylike) throws on ancient WebKit
- jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
-
- // Convert non-html into a text node
- } else if ( !rhtml.test( elem ) ) {
- nodes.push( context.createTextNode( elem ) );
-
- // Convert html into DOM nodes
- } else {
- tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
-
- // Deserialize a standard representation
- tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
- wrap = wrapMap[ tag ] || wrapMap._default;
- tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
-
- // Descend through wrappers to the right content
- j = wrap[ 0 ];
- while ( j-- ) {
- tmp = tmp.lastChild;
- }
-
- // Support: Android <=4.0 only, PhantomJS 1 only
- // push.apply(_, arraylike) throws on ancient WebKit
- jQuery.merge( nodes, tmp.childNodes );
-
- // Remember the top-level container
- tmp = fragment.firstChild;
-
- // Ensure the created nodes are orphaned (#12392)
- tmp.textContent = "";
- }
- }
- }
-
- // Remove wrapper from fragment
- fragment.textContent = "";
-
- i = 0;
- while ( ( elem = nodes[ i++ ] ) ) {
-
- // Skip elements already in the context collection (trac-4087)
- if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
- if ( ignored ) {
- ignored.push( elem );
- }
- continue;
- }
-
- attached = isAttached( elem );
-
- // Append to fragment
- tmp = getAll( fragment.appendChild( elem ), "script" );
-
- // Preserve script evaluation history
- if ( attached ) {
- setGlobalEval( tmp );
- }
-
- // Capture executables
- if ( scripts ) {
- j = 0;
- while ( ( elem = tmp[ j++ ] ) ) {
- if ( rscriptType.test( elem.type || "" ) ) {
- scripts.push( elem );
- }
- }
- }
- }
-
- return fragment;
-}
-
-
-( function() {
- var fragment = document.createDocumentFragment(),
- div = fragment.appendChild( document.createElement( "div" ) ),
- input = document.createElement( "input" );
-
- // Support: Android 4.0 - 4.3 only
- // Check state lost if the name is set (#11217)
- // Support: Windows Web Apps (WWA)
- // `name` and `type` must use .setAttribute for WWA (#14901)
- input.setAttribute( "type", "radio" );
- input.setAttribute( "checked", "checked" );
- input.setAttribute( "name", "t" );
-
- div.appendChild( input );
-
- // Support: Android <=4.1 only
- // Older WebKit doesn't clone checked state correctly in fragments
- support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
-
- // Support: IE <=11 only
- // Make sure textarea (and checkbox) defaultValue is properly cloned
- div.innerHTML = "";
- support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
-} )();
-
-
-var
- rkeyEvent = /^key/,
- rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
- rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
-
-function returnTrue() {
- return true;
-}
-
-function returnFalse() {
- return false;
-}
-
-// Support: IE <=9 - 11+
-// focus() and blur() are asynchronous, except when they are no-op.
-// So expect focus to be synchronous when the element is already active,
-// and blur to be synchronous when the element is not already active.
-// (focus and blur are always synchronous in other supported browsers,
-// this just defines when we can count on it).
-function expectSync( elem, type ) {
- return ( elem === safeActiveElement() ) === ( type === "focus" );
-}
-
-// Support: IE <=9 only
-// Accessing document.activeElement can throw unexpectedly
-// https://bugs.jquery.com/ticket/13393
-function safeActiveElement() {
- try {
- return document.activeElement;
- } catch ( err ) { }
-}
-
-function on( elem, types, selector, data, fn, one ) {
- var origFn, type;
-
- // Types can be a map of types/handlers
- if ( typeof types === "object" ) {
-
- // ( types-Object, selector, data )
- if ( typeof selector !== "string" ) {
-
- // ( types-Object, data )
- data = data || selector;
- selector = undefined;
- }
- for ( type in types ) {
- on( elem, type, selector, data, types[ type ], one );
- }
- return elem;
- }
-
- if ( data == null && fn == null ) {
-
- // ( types, fn )
- fn = selector;
- data = selector = undefined;
- } else if ( fn == null ) {
- if ( typeof selector === "string" ) {
-
- // ( types, selector, fn )
- fn = data;
- data = undefined;
- } else {
-
- // ( types, data, fn )
- fn = data;
- data = selector;
- selector = undefined;
- }
- }
- if ( fn === false ) {
- fn = returnFalse;
- } else if ( !fn ) {
- return elem;
- }
-
- if ( one === 1 ) {
- origFn = fn;
- fn = function( event ) {
-
- // Can use an empty set, since event contains the info
- jQuery().off( event );
- return origFn.apply( this, arguments );
- };
-
- // Use same guid so caller can remove using origFn
- fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
- }
- return elem.each( function() {
- jQuery.event.add( this, types, fn, data, selector );
- } );
-}
-
-/*
- * Helper functions for managing events -- not part of the public interface.
- * Props to Dean Edwards' addEvent library for many of the ideas.
- */
-jQuery.event = {
-
- global: {},
-
- add: function( elem, types, handler, data, selector ) {
-
- var handleObjIn, eventHandle, tmp,
- events, t, handleObj,
- special, handlers, type, namespaces, origType,
- elemData = dataPriv.get( elem );
-
- // Don't attach events to noData or text/comment nodes (but allow plain objects)
- if ( !elemData ) {
- return;
- }
-
- // Caller can pass in an object of custom data in lieu of the handler
- if ( handler.handler ) {
- handleObjIn = handler;
- handler = handleObjIn.handler;
- selector = handleObjIn.selector;
- }
-
- // Ensure that invalid selectors throw exceptions at attach time
- // Evaluate against documentElement in case elem is a non-element node (e.g., document)
- if ( selector ) {
- jQuery.find.matchesSelector( documentElement, selector );
- }
-
- // Make sure that the handler has a unique ID, used to find/remove it later
- if ( !handler.guid ) {
- handler.guid = jQuery.guid++;
- }
-
- // Init the element's event structure and main handler, if this is the first
- if ( !( events = elemData.events ) ) {
- events = elemData.events = {};
- }
- if ( !( eventHandle = elemData.handle ) ) {
- eventHandle = elemData.handle = function( e ) {
-
- // Discard the second event of a jQuery.event.trigger() and
- // when an event is called after a page has unloaded
- return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
- jQuery.event.dispatch.apply( elem, arguments ) : undefined;
- };
- }
-
- // Handle multiple events separated by a space
- types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
- t = types.length;
- while ( t-- ) {
- tmp = rtypenamespace.exec( types[ t ] ) || [];
- type = origType = tmp[ 1 ];
- namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
-
- // There *must* be a type, no attaching namespace-only handlers
- if ( !type ) {
- continue;
- }
-
- // If event changes its type, use the special event handlers for the changed type
- special = jQuery.event.special[ type ] || {};
-
- // If selector defined, determine special event api type, otherwise given type
- type = ( selector ? special.delegateType : special.bindType ) || type;
-
- // Update special based on newly reset type
- special = jQuery.event.special[ type ] || {};
-
- // handleObj is passed to all event handlers
- handleObj = jQuery.extend( {
- type: type,
- origType: origType,
- data: data,
- handler: handler,
- guid: handler.guid,
- selector: selector,
- needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
- namespace: namespaces.join( "." )
- }, handleObjIn );
-
- // Init the event handler queue if we're the first
- if ( !( handlers = events[ type ] ) ) {
- handlers = events[ type ] = [];
- handlers.delegateCount = 0;
-
- // Only use addEventListener if the special events handler returns false
- if ( !special.setup ||
- special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
-
- if ( elem.addEventListener ) {
- elem.addEventListener( type, eventHandle );
- }
- }
- }
-
- if ( special.add ) {
- special.add.call( elem, handleObj );
-
- if ( !handleObj.handler.guid ) {
- handleObj.handler.guid = handler.guid;
- }
- }
-
- // Add to the element's handler list, delegates in front
- if ( selector ) {
- handlers.splice( handlers.delegateCount++, 0, handleObj );
- } else {
- handlers.push( handleObj );
- }
-
- // Keep track of which events have ever been used, for event optimization
- jQuery.event.global[ type ] = true;
- }
-
- },
-
- // Detach an event or set of events from an element
- remove: function( elem, types, handler, selector, mappedTypes ) {
-
- var j, origCount, tmp,
- events, t, handleObj,
- special, handlers, type, namespaces, origType,
- elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
-
- if ( !elemData || !( events = elemData.events ) ) {
- return;
- }
-
- // Once for each type.namespace in types; type may be omitted
- types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
- t = types.length;
- while ( t-- ) {
- tmp = rtypenamespace.exec( types[ t ] ) || [];
- type = origType = tmp[ 1 ];
- namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
-
- // Unbind all events (on this namespace, if provided) for the element
- if ( !type ) {
- for ( type in events ) {
- jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
- }
- continue;
- }
-
- special = jQuery.event.special[ type ] || {};
- type = ( selector ? special.delegateType : special.bindType ) || type;
- handlers = events[ type ] || [];
- tmp = tmp[ 2 ] &&
- new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
-
- // Remove matching events
- origCount = j = handlers.length;
- while ( j-- ) {
- handleObj = handlers[ j ];
-
- if ( ( mappedTypes || origType === handleObj.origType ) &&
- ( !handler || handler.guid === handleObj.guid ) &&
- ( !tmp || tmp.test( handleObj.namespace ) ) &&
- ( !selector || selector === handleObj.selector ||
- selector === "**" && handleObj.selector ) ) {
- handlers.splice( j, 1 );
-
- if ( handleObj.selector ) {
- handlers.delegateCount--;
- }
- if ( special.remove ) {
- special.remove.call( elem, handleObj );
- }
- }
- }
-
- // Remove generic event handler if we removed something and no more handlers exist
- // (avoids potential for endless recursion during removal of special event handlers)
- if ( origCount && !handlers.length ) {
- if ( !special.teardown ||
- special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
-
- jQuery.removeEvent( elem, type, elemData.handle );
- }
-
- delete events[ type ];
- }
- }
-
- // Remove data and the expando if it's no longer used
- if ( jQuery.isEmptyObject( events ) ) {
- dataPriv.remove( elem, "handle events" );
- }
- },
-
- dispatch: function( nativeEvent ) {
-
- // Make a writable jQuery.Event from the native event object
- var event = jQuery.event.fix( nativeEvent );
-
- var i, j, ret, matched, handleObj, handlerQueue,
- args = new Array( arguments.length ),
- handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
- special = jQuery.event.special[ event.type ] || {};
-
- // Use the fix-ed jQuery.Event rather than the (read-only) native event
- args[ 0 ] = event;
-
- for ( i = 1; i < arguments.length; i++ ) {
- args[ i ] = arguments[ i ];
- }
-
- event.delegateTarget = this;
-
- // Call the preDispatch hook for the mapped type, and let it bail if desired
- if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
- return;
- }
-
- // Determine handlers
- handlerQueue = jQuery.event.handlers.call( this, event, handlers );
-
- // Run delegates first; they may want to stop propagation beneath us
- i = 0;
- while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
- event.currentTarget = matched.elem;
-
- j = 0;
- while ( ( handleObj = matched.handlers[ j++ ] ) &&
- !event.isImmediatePropagationStopped() ) {
-
- // If the event is namespaced, then each handler is only invoked if it is
- // specially universal or its namespaces are a superset of the event's.
- if ( !event.rnamespace || handleObj.namespace === false ||
- event.rnamespace.test( handleObj.namespace ) ) {
-
- event.handleObj = handleObj;
- event.data = handleObj.data;
-
- ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
- handleObj.handler ).apply( matched.elem, args );
-
- if ( ret !== undefined ) {
- if ( ( event.result = ret ) === false ) {
- event.preventDefault();
- event.stopPropagation();
- }
- }
- }
- }
- }
-
- // Call the postDispatch hook for the mapped type
- if ( special.postDispatch ) {
- special.postDispatch.call( this, event );
- }
-
- return event.result;
- },
-
- handlers: function( event, handlers ) {
- var i, handleObj, sel, matchedHandlers, matchedSelectors,
- handlerQueue = [],
- delegateCount = handlers.delegateCount,
- cur = event.target;
-
- // Find delegate handlers
- if ( delegateCount &&
-
- // Support: IE <=9
- // Black-hole SVG instance trees (trac-13180)
- cur.nodeType &&
-
- // Support: Firefox <=42
- // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
- // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
- // Support: IE 11 only
- // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
- !( event.type === "click" && event.button >= 1 ) ) {
-
- for ( ; cur !== this; cur = cur.parentNode || this ) {
-
- // Don't check non-elements (#13208)
- // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
- if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
- matchedHandlers = [];
- matchedSelectors = {};
- for ( i = 0; i < delegateCount; i++ ) {
- handleObj = handlers[ i ];
-
- // Don't conflict with Object.prototype properties (#13203)
- sel = handleObj.selector + " ";
-
- if ( matchedSelectors[ sel ] === undefined ) {
- matchedSelectors[ sel ] = handleObj.needsContext ?
- jQuery( sel, this ).index( cur ) > -1 :
- jQuery.find( sel, this, null, [ cur ] ).length;
- }
- if ( matchedSelectors[ sel ] ) {
- matchedHandlers.push( handleObj );
- }
- }
- if ( matchedHandlers.length ) {
- handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
- }
- }
- }
- }
-
- // Add the remaining (directly-bound) handlers
- cur = this;
- if ( delegateCount < handlers.length ) {
- handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
- }
-
- return handlerQueue;
- },
-
- addProp: function( name, hook ) {
- Object.defineProperty( jQuery.Event.prototype, name, {
- enumerable: true,
- configurable: true,
-
- get: isFunction( hook ) ?
- function() {
- if ( this.originalEvent ) {
- return hook( this.originalEvent );
- }
- } :
- function() {
- if ( this.originalEvent ) {
- return this.originalEvent[ name ];
- }
- },
-
- set: function( value ) {
- Object.defineProperty( this, name, {
- enumerable: true,
- configurable: true,
- writable: true,
- value: value
- } );
- }
- } );
- },
-
- fix: function( originalEvent ) {
- return originalEvent[ jQuery.expando ] ?
- originalEvent :
- new jQuery.Event( originalEvent );
- },
-
- special: {
- load: {
-
- // Prevent triggered image.load events from bubbling to window.load
- noBubble: true
- },
- click: {
-
- // Utilize native event to ensure correct state for checkable inputs
- setup: function( data ) {
-
- // For mutual compressibility with _default, replace `this` access with a local var.
- // `|| data` is dead code meant only to preserve the variable through minification.
- var el = this || data;
-
- // Claim the first handler
- if ( rcheckableType.test( el.type ) &&
- el.click && nodeName( el, "input" ) ) {
-
- // dataPriv.set( el, "click", ... )
- leverageNative( el, "click", returnTrue );
- }
-
- // Return false to allow normal processing in the caller
- return false;
- },
- trigger: function( data ) {
-
- // For mutual compressibility with _default, replace `this` access with a local var.
- // `|| data` is dead code meant only to preserve the variable through minification.
- var el = this || data;
-
- // Force setup before triggering a click
- if ( rcheckableType.test( el.type ) &&
- el.click && nodeName( el, "input" ) ) {
-
- leverageNative( el, "click" );
- }
-
- // Return non-false to allow normal event-path propagation
- return true;
- },
-
- // For cross-browser consistency, suppress native .click() on links
- // Also prevent it if we're currently inside a leveraged native-event stack
- _default: function( event ) {
- var target = event.target;
- return rcheckableType.test( target.type ) &&
- target.click && nodeName( target, "input" ) &&
- dataPriv.get( target, "click" ) ||
- nodeName( target, "a" );
- }
- },
-
- beforeunload: {
- postDispatch: function( event ) {
-
- // Support: Firefox 20+
- // Firefox doesn't alert if the returnValue field is not set.
- if ( event.result !== undefined && event.originalEvent ) {
- event.originalEvent.returnValue = event.result;
- }
- }
- }
- }
-};
-
-// Ensure the presence of an event listener that handles manually-triggered
-// synthetic events by interrupting progress until reinvoked in response to
-// *native* events that it fires directly, ensuring that state changes have
-// already occurred before other listeners are invoked.
-function leverageNative( el, type, expectSync ) {
-
- // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add
- if ( !expectSync ) {
- if ( dataPriv.get( el, type ) === undefined ) {
- jQuery.event.add( el, type, returnTrue );
- }
- return;
- }
-
- // Register the controller as a special universal handler for all event namespaces
- dataPriv.set( el, type, false );
- jQuery.event.add( el, type, {
- namespace: false,
- handler: function( event ) {
- var notAsync, result,
- saved = dataPriv.get( this, type );
-
- if ( ( event.isTrigger & 1 ) && this[ type ] ) {
-
- // Interrupt processing of the outer synthetic .trigger()ed event
- // Saved data should be false in such cases, but might be a leftover capture object
- // from an async native handler (gh-4350)
- if ( !saved.length ) {
-
- // Store arguments for use when handling the inner native event
- // There will always be at least one argument (an event object), so this array
- // will not be confused with a leftover capture object.
- saved = slice.call( arguments );
- dataPriv.set( this, type, saved );
-
- // Trigger the native event and capture its result
- // Support: IE <=9 - 11+
- // focus() and blur() are asynchronous
- notAsync = expectSync( this, type );
- this[ type ]();
- result = dataPriv.get( this, type );
- if ( saved !== result || notAsync ) {
- dataPriv.set( this, type, false );
- } else {
- result = {};
- }
- if ( saved !== result ) {
-
- // Cancel the outer synthetic event
- event.stopImmediatePropagation();
- event.preventDefault();
- return result.value;
- }
-
- // If this is an inner synthetic event for an event with a bubbling surrogate
- // (focus or blur), assume that the surrogate already propagated from triggering the
- // native event and prevent that from happening again here.
- // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the
- // bubbling surrogate propagates *after* the non-bubbling base), but that seems
- // less bad than duplication.
- } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {
- event.stopPropagation();
- }
-
- // If this is a native event triggered above, everything is now in order
- // Fire an inner synthetic event with the original arguments
- } else if ( saved.length ) {
-
- // ...and capture the result
- dataPriv.set( this, type, {
- value: jQuery.event.trigger(
-
- // Support: IE <=9 - 11+
- // Extend with the prototype to reset the above stopImmediatePropagation()
- jQuery.extend( saved[ 0 ], jQuery.Event.prototype ),
- saved.slice( 1 ),
- this
- )
- } );
-
- // Abort handling of the native event
- event.stopImmediatePropagation();
- }
- }
- } );
-}
-
-jQuery.removeEvent = function( elem, type, handle ) {
-
- // This "if" is needed for plain objects
- if ( elem.removeEventListener ) {
- elem.removeEventListener( type, handle );
- }
-};
-
-jQuery.Event = function( src, props ) {
-
- // Allow instantiation without the 'new' keyword
- if ( !( this instanceof jQuery.Event ) ) {
- return new jQuery.Event( src, props );
- }
-
- // Event object
- if ( src && src.type ) {
- this.originalEvent = src;
- this.type = src.type;
-
- // Events bubbling up the document may have been marked as prevented
- // by a handler lower down the tree; reflect the correct value.
- this.isDefaultPrevented = src.defaultPrevented ||
- src.defaultPrevented === undefined &&
-
- // Support: Android <=2.3 only
- src.returnValue === false ?
- returnTrue :
- returnFalse;
-
- // Create target properties
- // Support: Safari <=6 - 7 only
- // Target should not be a text node (#504, #13143)
- this.target = ( src.target && src.target.nodeType === 3 ) ?
- src.target.parentNode :
- src.target;
-
- this.currentTarget = src.currentTarget;
- this.relatedTarget = src.relatedTarget;
-
- // Event type
- } else {
- this.type = src;
- }
-
- // Put explicitly provided properties onto the event object
- if ( props ) {
- jQuery.extend( this, props );
- }
-
- // Create a timestamp if incoming event doesn't have one
- this.timeStamp = src && src.timeStamp || Date.now();
-
- // Mark it as fixed
- this[ jQuery.expando ] = true;
-};
-
-// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
-// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
-jQuery.Event.prototype = {
- constructor: jQuery.Event,
- isDefaultPrevented: returnFalse,
- isPropagationStopped: returnFalse,
- isImmediatePropagationStopped: returnFalse,
- isSimulated: false,
-
- preventDefault: function() {
- var e = this.originalEvent;
-
- this.isDefaultPrevented = returnTrue;
-
- if ( e && !this.isSimulated ) {
- e.preventDefault();
- }
- },
- stopPropagation: function() {
- var e = this.originalEvent;
-
- this.isPropagationStopped = returnTrue;
-
- if ( e && !this.isSimulated ) {
- e.stopPropagation();
- }
- },
- stopImmediatePropagation: function() {
- var e = this.originalEvent;
-
- this.isImmediatePropagationStopped = returnTrue;
-
- if ( e && !this.isSimulated ) {
- e.stopImmediatePropagation();
- }
-
- this.stopPropagation();
- }
-};
-
-// Includes all common event props including KeyEvent and MouseEvent specific props
-jQuery.each( {
- altKey: true,
- bubbles: true,
- cancelable: true,
- changedTouches: true,
- ctrlKey: true,
- detail: true,
- eventPhase: true,
- metaKey: true,
- pageX: true,
- pageY: true,
- shiftKey: true,
- view: true,
- "char": true,
- code: true,
- charCode: true,
- key: true,
- keyCode: true,
- button: true,
- buttons: true,
- clientX: true,
- clientY: true,
- offsetX: true,
- offsetY: true,
- pointerId: true,
- pointerType: true,
- screenX: true,
- screenY: true,
- targetTouches: true,
- toElement: true,
- touches: true,
-
- which: function( event ) {
- var button = event.button;
-
- // Add which for key events
- if ( event.which == null && rkeyEvent.test( event.type ) ) {
- return event.charCode != null ? event.charCode : event.keyCode;
- }
-
- // Add which for click: 1 === left; 2 === middle; 3 === right
- if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
- if ( button & 1 ) {
- return 1;
- }
-
- if ( button & 2 ) {
- return 3;
- }
-
- if ( button & 4 ) {
- return 2;
- }
-
- return 0;
- }
-
- return event.which;
- }
-}, jQuery.event.addProp );
-
-jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
- jQuery.event.special[ type ] = {
-
- // Utilize native event if possible so blur/focus sequence is correct
- setup: function() {
-
- // Claim the first handler
- // dataPriv.set( this, "focus", ... )
- // dataPriv.set( this, "blur", ... )
- leverageNative( this, type, expectSync );
-
- // Return false to allow normal processing in the caller
- return false;
- },
- trigger: function() {
-
- // Force setup before trigger
- leverageNative( this, type );
-
- // Return non-false to allow normal event-path propagation
- return true;
- },
-
- delegateType: delegateType
- };
-} );
-
-// Create mouseenter/leave events using mouseover/out and event-time checks
-// so that event delegation works in jQuery.
-// Do the same for pointerenter/pointerleave and pointerover/pointerout
-//
-// Support: Safari 7 only
-// Safari sends mouseenter too often; see:
-// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
-// for the description of the bug (it existed in older Chrome versions as well).
-jQuery.each( {
- mouseenter: "mouseover",
- mouseleave: "mouseout",
- pointerenter: "pointerover",
- pointerleave: "pointerout"
-}, function( orig, fix ) {
- jQuery.event.special[ orig ] = {
- delegateType: fix,
- bindType: fix,
-
- handle: function( event ) {
- var ret,
- target = this,
- related = event.relatedTarget,
- handleObj = event.handleObj;
-
- // For mouseenter/leave call the handler if related is outside the target.
- // NB: No relatedTarget if the mouse left/entered the browser window
- if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
- event.type = handleObj.origType;
- ret = handleObj.handler.apply( this, arguments );
- event.type = fix;
- }
- return ret;
- }
- };
-} );
-
-jQuery.fn.extend( {
-
- on: function( types, selector, data, fn ) {
- return on( this, types, selector, data, fn );
- },
- one: function( types, selector, data, fn ) {
- return on( this, types, selector, data, fn, 1 );
- },
- off: function( types, selector, fn ) {
- var handleObj, type;
- if ( types && types.preventDefault && types.handleObj ) {
-
- // ( event ) dispatched jQuery.Event
- handleObj = types.handleObj;
- jQuery( types.delegateTarget ).off(
- handleObj.namespace ?
- handleObj.origType + "." + handleObj.namespace :
- handleObj.origType,
- handleObj.selector,
- handleObj.handler
- );
- return this;
- }
- if ( typeof types === "object" ) {
-
- // ( types-object [, selector] )
- for ( type in types ) {
- this.off( type, selector, types[ type ] );
- }
- return this;
- }
- if ( selector === false || typeof selector === "function" ) {
-
- // ( types [, fn] )
- fn = selector;
- selector = undefined;
- }
- if ( fn === false ) {
- fn = returnFalse;
- }
- return this.each( function() {
- jQuery.event.remove( this, types, fn, selector );
- } );
- }
-} );
-
-
-var
-
- /* eslint-disable max-len */
-
- // See https://github.com/eslint/eslint/issues/3229
- rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
-
- /* eslint-enable */
-
- // Support: IE <=10 - 11, Edge 12 - 13 only
- // In IE/Edge using regex groups here causes severe slowdowns.
- // See https://connect.microsoft.com/IE/feedback/details/1736512/
- rnoInnerhtml = /