" gives ticks linearly spaced in data (not in position) every (float) f
@@ -55,28 +51,26 @@ module.exports = function handleTickValueDefaults(containerIn, containerOut, coe
// "D1" gives powers of 10 with all small digits between, "D2" gives only 2 and 5
(axType === 'log' && prefix === 'D' && (dtickNum === 1 || dtickNum === 2))
)) {
- containerOut.dtick = dtickDflt;
- }
- }
+ containerOut.dtick = dtickDflt
+ }
+ }
// tick0 can have different valType for different axis types, so
// validate that now. Also for dates, change milliseconds to date strings
- var tick0Dflt = (axType === 'date') ? Lib.dateTick0(containerOut.calendar) : 0;
- var tick0 = coerce('tick0', tick0Dflt);
- if(axType === 'date') {
- containerOut.tick0 = Lib.cleanDate(tick0, tick0Dflt);
- }
- // Aside from date axes, dtick must be numeric; D1 and D2 modes ignore tick0 entirely
- else if(isNumeric(tick0) && dtick !== 'D1' && dtick !== 'D2') {
- containerOut.tick0 = Number(tick0);
- }
- else {
- containerOut.tick0 = tick0Dflt;
- }
+ var tick0Dflt = (axType === 'date') ? Lib.dateTick0(containerOut.calendar) : 0
+ var tick0 = coerce('tick0', tick0Dflt)
+ if (axType === 'date') {
+ containerOut.tick0 = Lib.cleanDate(tick0, tick0Dflt)
}
- else {
- var tickvals = coerce('tickvals');
- if(tickvals === undefined) containerOut.tickmode = 'auto';
- else coerce('ticktext');
+ // Aside from date axes, dtick must be numeric; D1 and D2 modes ignore tick0 entirely
+ else if (isNumeric(tick0) && dtick !== 'D1' && dtick !== 'D2') {
+ containerOut.tick0 = Number(tick0)
+ } else {
+ containerOut.tick0 = tick0Dflt
}
-};
+ } else {
+ var tickvals = coerce('tickvals')
+ if (tickvals === undefined) containerOut.tickmode = 'auto'
+ else coerce('ticktext')
+ }
+}
diff --git a/src/plots/cartesian/transition_axes.js b/src/plots/cartesian/transition_axes.js
index b41c50b8cc3..af0ad929a80 100644
--- a/src/plots/cartesian/transition_axes.js
+++ b/src/plots/cartesian/transition_axes.js
@@ -6,142 +6,141 @@
* LICENSE file in the root directory of this source tree.
*/
-
-'use strict';
-
-var d3 = require('d3');
-
-var Plotly = require('../../plotly');
-var Registry = require('../../registry');
-var Drawing = require('../../components/drawing');
-var Axes = require('./axes');
-var axisRegex = /((x|y)([2-9]|[1-9][0-9]+)?)axis$/;
-
-module.exports = function transitionAxes(gd, newLayout, transitionOpts, makeOnCompleteCallback) {
- var fullLayout = gd._fullLayout;
- var axes = [];
-
- function computeUpdates(layout) {
- var ai, attrList, match, axis, update;
- var updates = {};
-
- for(ai in layout) {
- attrList = ai.split('.');
- match = attrList[0].match(axisRegex);
- if(match) {
- var axisLetter = match[1];
- var axisName = axisLetter + 'axis';
- axis = fullLayout[axisName];
- update = {};
-
- if(Array.isArray(layout[ai])) {
- update.to = layout[ai].slice(0);
- } else {
- if(Array.isArray(layout[ai].range)) {
- update.to = layout[ai].range.slice(0);
- }
- }
- if(!update.to) continue;
-
- update.axisName = axisName;
- update.length = axis._length;
-
- axes.push(axisLetter);
-
- updates[axisLetter] = update;
- }
+'use strict'
+
+var d3 = require('d3')
+
+var Plotly = require('../../plotly')
+var Registry = require('../../registry')
+var Drawing = require('../../components/drawing')
+var Axes = require('./axes')
+var axisRegex = /((x|y)([2-9]|[1-9][0-9]+)?)axis$/
+
+module.exports = function transitionAxes (gd, newLayout, transitionOpts, makeOnCompleteCallback) {
+ var fullLayout = gd._fullLayout
+ var axes = []
+
+ function computeUpdates (layout) {
+ var ai, attrList, match, axis, update
+ var updates = {}
+
+ for (ai in layout) {
+ attrList = ai.split('.')
+ match = attrList[0].match(axisRegex)
+ if (match) {
+ var axisLetter = match[1]
+ var axisName = axisLetter + 'axis'
+ axis = fullLayout[axisName]
+ update = {}
+
+ if (Array.isArray(layout[ai])) {
+ update.to = layout[ai].slice(0)
+ } else {
+ if (Array.isArray(layout[ai].range)) {
+ update.to = layout[ai].range.slice(0)
+ }
}
+ if (!update.to) continue
+
+ update.axisName = axisName
+ update.length = axis._length
- return updates;
+ axes.push(axisLetter)
+
+ updates[axisLetter] = update
+ }
}
- function computeAffectedSubplots(fullLayout, updatedAxisIds, updates) {
- var plotName;
- var plotinfos = fullLayout._plots;
- var affectedSubplots = [];
- var toX, toY;
+ return updates
+ }
- for(plotName in plotinfos) {
- var plotinfo = plotinfos[plotName];
+ function computeAffectedSubplots (fullLayout, updatedAxisIds, updates) {
+ var plotName
+ var plotinfos = fullLayout._plots
+ var affectedSubplots = []
+ var toX, toY
- if(affectedSubplots.indexOf(plotinfo) !== -1) continue;
+ for (plotName in plotinfos) {
+ var plotinfo = plotinfos[plotName]
- var x = plotinfo.xaxis._id;
- var y = plotinfo.yaxis._id;
- var fromX = plotinfo.xaxis.range;
- var fromY = plotinfo.yaxis.range;
+ if (affectedSubplots.indexOf(plotinfo) !== -1) continue
- // Store the initial range at the beginning of this transition:
- plotinfo.xaxis._r = plotinfo.xaxis.range.slice();
- plotinfo.yaxis._r = plotinfo.yaxis.range.slice();
-
- if(updates[x]) {
- toX = updates[x].to;
- } else {
- toX = fromX;
- }
- if(updates[y]) {
- toY = updates[y].to;
- } else {
- toY = fromY;
- }
-
- if(fromX[0] === toX[0] && fromX[1] === toX[1] && fromY[0] === toY[0] && fromY[1] === toY[1]) continue;
-
- if(updatedAxisIds.indexOf(x) !== -1 || updatedAxisIds.indexOf(y) !== -1) {
- affectedSubplots.push(plotinfo);
- }
- }
+ var x = plotinfo.xaxis._id
+ var y = plotinfo.yaxis._id
+ var fromX = plotinfo.xaxis.range
+ var fromY = plotinfo.yaxis.range
- return affectedSubplots;
+ // Store the initial range at the beginning of this transition:
+ plotinfo.xaxis._r = plotinfo.xaxis.range.slice()
+ plotinfo.yaxis._r = plotinfo.yaxis.range.slice()
+
+ if (updates[x]) {
+ toX = updates[x].to
+ } else {
+ toX = fromX
+ }
+ if (updates[y]) {
+ toY = updates[y].to
+ } else {
+ toY = fromY
+ }
+
+ if (fromX[0] === toX[0] && fromX[1] === toX[1] && fromY[0] === toY[0] && fromY[1] === toY[1]) continue
+
+ if (updatedAxisIds.indexOf(x) !== -1 || updatedAxisIds.indexOf(y) !== -1) {
+ affectedSubplots.push(plotinfo)
+ }
}
- var updates = computeUpdates(newLayout);
- var updatedAxisIds = Object.keys(updates);
- var affectedSubplots = computeAffectedSubplots(fullLayout, updatedAxisIds, updates);
+ return affectedSubplots
+ }
- if(!affectedSubplots.length) {
- return false;
- }
+ var updates = computeUpdates(newLayout)
+ var updatedAxisIds = Object.keys(updates)
+ var affectedSubplots = computeAffectedSubplots(fullLayout, updatedAxisIds, updates)
- function ticksAndAnnotations(xa, ya) {
- var activeAxIds = [],
- i;
+ if (!affectedSubplots.length) {
+ return false
+ }
- activeAxIds = [xa._id, ya._id];
+ function ticksAndAnnotations (xa, ya) {
+ var activeAxIds = [],
+ i
- for(i = 0; i < activeAxIds.length; i++) {
- Axes.doTicks(gd, activeAxIds[i], true);
- }
+ activeAxIds = [xa._id, ya._id]
+
+ for (i = 0; i < activeAxIds.length; i++) {
+ Axes.doTicks(gd, activeAxIds[i], true)
+ }
- function redrawObjs(objArray, method) {
- for(i = 0; i < objArray.length; i++) {
- var obji = objArray[i];
+ function redrawObjs (objArray, method) {
+ for (i = 0; i < objArray.length; i++) {
+ var obji = objArray[i]
- if((activeAxIds.indexOf(obji.xref) !== -1) ||
+ if ((activeAxIds.indexOf(obji.xref) !== -1) ||
(activeAxIds.indexOf(obji.yref) !== -1)) {
- method(gd, i);
- }
- }
+ method(gd, i)
}
+ }
+ }
// annotations and shapes 'draw' method is slow,
// use the finer-grained 'drawOne' method instead
- redrawObjs(fullLayout.annotations || [], Registry.getComponentMethod('annotations', 'drawOne'));
- redrawObjs(fullLayout.shapes || [], Registry.getComponentMethod('shapes', 'drawOne'));
- redrawObjs(fullLayout.images || [], Registry.getComponentMethod('images', 'draw'));
- }
+ redrawObjs(fullLayout.annotations || [], Registry.getComponentMethod('annotations', 'drawOne'))
+ redrawObjs(fullLayout.shapes || [], Registry.getComponentMethod('shapes', 'drawOne'))
+ redrawObjs(fullLayout.images || [], Registry.getComponentMethod('images', 'draw'))
+ }
- function unsetSubplotTransform(subplot) {
- var xa2 = subplot.xaxis;
- var ya2 = subplot.yaxis;
+ function unsetSubplotTransform (subplot) {
+ var xa2 = subplot.xaxis
+ var ya2 = subplot.yaxis
- fullLayout._defs.selectAll('#' + subplot.clipId)
+ fullLayout._defs.selectAll('#' + subplot.clipId)
.call(Drawing.setTranslate, 0, 0)
- .call(Drawing.setScale, 1, 1);
+ .call(Drawing.setScale, 1, 1)
- subplot.plot
+ subplot.plot
.call(Drawing.setTranslate, xa2._offset, ya2._offset)
.call(Drawing.setScale, 1, 1)
@@ -149,77 +148,75 @@ module.exports = function transitionAxes(gd, newLayout, transitionOpts, makeOnCo
// scale to individual points to counteract the scale of the trace
// as a whole:
.selectAll('.points').selectAll('.point')
- .call(Drawing.setPointGroupScale, 1, 1);
-
+ .call(Drawing.setPointGroupScale, 1, 1)
+ }
+
+ function updateSubplot (subplot, progress) {
+ var axis, r0, r1
+ var xUpdate = updates[subplot.xaxis._id]
+ var yUpdate = updates[subplot.yaxis._id]
+
+ var viewBox = []
+
+ if (xUpdate) {
+ axis = gd._fullLayout[xUpdate.axisName]
+ r0 = axis._r
+ r1 = xUpdate.to
+ viewBox[0] = (r0[0] * (1 - progress) + progress * r1[0] - r0[0]) / (r0[1] - r0[0]) * subplot.xaxis._length
+ var dx1 = r0[1] - r0[0]
+ var dx2 = r1[1] - r1[0]
+
+ axis.range[0] = r0[0] * (1 - progress) + progress * r1[0]
+ axis.range[1] = r0[1] * (1 - progress) + progress * r1[1]
+
+ viewBox[2] = subplot.xaxis._length * ((1 - progress) + progress * dx2 / dx1)
+ } else {
+ viewBox[0] = 0
+ viewBox[2] = subplot.xaxis._length
}
- function updateSubplot(subplot, progress) {
- var axis, r0, r1;
- var xUpdate = updates[subplot.xaxis._id];
- var yUpdate = updates[subplot.yaxis._id];
-
- var viewBox = [];
-
- if(xUpdate) {
- axis = gd._fullLayout[xUpdate.axisName];
- r0 = axis._r;
- r1 = xUpdate.to;
- viewBox[0] = (r0[0] * (1 - progress) + progress * r1[0] - r0[0]) / (r0[1] - r0[0]) * subplot.xaxis._length;
- var dx1 = r0[1] - r0[0];
- var dx2 = r1[1] - r1[0];
-
- axis.range[0] = r0[0] * (1 - progress) + progress * r1[0];
- axis.range[1] = r0[1] * (1 - progress) + progress * r1[1];
-
- viewBox[2] = subplot.xaxis._length * ((1 - progress) + progress * dx2 / dx1);
- } else {
- viewBox[0] = 0;
- viewBox[2] = subplot.xaxis._length;
- }
-
- if(yUpdate) {
- axis = gd._fullLayout[yUpdate.axisName];
- r0 = axis._r;
- r1 = yUpdate.to;
- viewBox[1] = (r0[1] * (1 - progress) + progress * r1[1] - r0[1]) / (r0[0] - r0[1]) * subplot.yaxis._length;
- var dy1 = r0[1] - r0[0];
- var dy2 = r1[1] - r1[0];
-
- axis.range[0] = r0[0] * (1 - progress) + progress * r1[0];
- axis.range[1] = r0[1] * (1 - progress) + progress * r1[1];
-
- viewBox[3] = subplot.yaxis._length * ((1 - progress) + progress * dy2 / dy1);
- } else {
- viewBox[1] = 0;
- viewBox[3] = subplot.yaxis._length;
- }
-
- ticksAndAnnotations(subplot.xaxis, subplot.yaxis);
+ if (yUpdate) {
+ axis = gd._fullLayout[yUpdate.axisName]
+ r0 = axis._r
+ r1 = yUpdate.to
+ viewBox[1] = (r0[1] * (1 - progress) + progress * r1[1] - r0[1]) / (r0[0] - r0[1]) * subplot.yaxis._length
+ var dy1 = r0[1] - r0[0]
+ var dy2 = r1[1] - r1[0]
+
+ axis.range[0] = r0[0] * (1 - progress) + progress * r1[0]
+ axis.range[1] = r0[1] * (1 - progress) + progress * r1[1]
+
+ viewBox[3] = subplot.yaxis._length * ((1 - progress) + progress * dy2 / dy1)
+ } else {
+ viewBox[1] = 0
+ viewBox[3] = subplot.yaxis._length
+ }
+ ticksAndAnnotations(subplot.xaxis, subplot.yaxis)
- var xa2 = subplot.xaxis;
- var ya2 = subplot.yaxis;
+ var xa2 = subplot.xaxis
+ var ya2 = subplot.yaxis
- var editX = !!xUpdate;
- var editY = !!yUpdate;
+ var editX = !!xUpdate
+ var editY = !!yUpdate
- var xScaleFactor = editX ? xa2._length / viewBox[2] : 1,
- yScaleFactor = editY ? ya2._length / viewBox[3] : 1;
+ var xScaleFactor = editX ? xa2._length / viewBox[2] : 1,
+ yScaleFactor = editY ? ya2._length / viewBox[3] : 1
- var clipDx = editX ? viewBox[0] : 0,
- clipDy = editY ? viewBox[1] : 0;
+ var clipDx = editX ? viewBox[0] : 0,
+ clipDy = editY ? viewBox[1] : 0
- var fracDx = editX ? (viewBox[0] / viewBox[2] * xa2._length) : 0,
- fracDy = editY ? (viewBox[1] / viewBox[3] * ya2._length) : 0;
+ var fracDx = editX ? (viewBox[0] / viewBox[2] * xa2._length) : 0,
+ fracDy = editY ? (viewBox[1] / viewBox[3] * ya2._length) : 0
- var plotDx = xa2._offset - fracDx,
- plotDy = ya2._offset - fracDy;
+ var plotDx = xa2._offset - fracDx,
+ plotDy = ya2._offset - fracDy
- fullLayout._defs.selectAll('#' + subplot.clipId)
+ fullLayout._defs.selectAll('#' + subplot.clipId)
.call(Drawing.setTranslate, clipDx, clipDy)
- .call(Drawing.setScale, 1 / xScaleFactor, 1 / yScaleFactor);
+ .call(Drawing.setScale, 1 / xScaleFactor, 1 / yScaleFactor)
- subplot.plot
+ subplot.plot
.call(Drawing.setTranslate, plotDx, plotDy)
.call(Drawing.setScale, xScaleFactor, yScaleFactor)
@@ -227,84 +224,83 @@ module.exports = function transitionAxes(gd, newLayout, transitionOpts, makeOnCo
// scale to individual points to counteract the scale of the trace
// as a whole:
.selectAll('.points').selectAll('.point')
- .call(Drawing.setPointGroupScale, 1 / xScaleFactor, 1 / yScaleFactor);
-
- }
+ .call(Drawing.setPointGroupScale, 1 / xScaleFactor, 1 / yScaleFactor)
+ }
- var onComplete;
- if(makeOnCompleteCallback) {
+ var onComplete
+ if (makeOnCompleteCallback) {
// This module makes the choice whether or not it notifies Plotly.transition
// about completion:
- onComplete = makeOnCompleteCallback();
+ onComplete = makeOnCompleteCallback()
+ }
+
+ function transitionComplete () {
+ var aobj = {}
+ for (var i = 0; i < updatedAxisIds.length; i++) {
+ var axi = gd._fullLayout[updates[updatedAxisIds[i]].axisName]
+ var to = updates[updatedAxisIds[i]].to
+ aobj[axi._name + '.range[0]'] = to[0]
+ aobj[axi._name + '.range[1]'] = to[1]
+
+ axi.range = to.slice()
}
- function transitionComplete() {
- var aobj = {};
- for(var i = 0; i < updatedAxisIds.length; i++) {
- var axi = gd._fullLayout[updates[updatedAxisIds[i]].axisName];
- var to = updates[updatedAxisIds[i]].to;
- aobj[axi._name + '.range[0]'] = to[0];
- aobj[axi._name + '.range[1]'] = to[1];
-
- axi.range = to.slice();
- }
-
// Signal that this transition has completed:
- onComplete && onComplete();
-
- return Plotly.relayout(gd, aobj).then(function() {
- for(var i = 0; i < affectedSubplots.length; i++) {
- unsetSubplotTransform(affectedSubplots[i]);
- }
- });
+ onComplete && onComplete()
+
+ return Plotly.relayout(gd, aobj).then(function () {
+ for (var i = 0; i < affectedSubplots.length; i++) {
+ unsetSubplotTransform(affectedSubplots[i])
+ }
+ })
+ }
+
+ function transitionInterrupt () {
+ var aobj = {}
+ for (var i = 0; i < updatedAxisIds.length; i++) {
+ var axi = gd._fullLayout[updatedAxisIds[i] + 'axis']
+ aobj[axi._name + '.range[0]'] = axi.range[0]
+ aobj[axi._name + '.range[1]'] = axi.range[1]
+
+ axi.range = axi._r.slice()
}
- function transitionInterrupt() {
- var aobj = {};
- for(var i = 0; i < updatedAxisIds.length; i++) {
- var axi = gd._fullLayout[updatedAxisIds[i] + 'axis'];
- aobj[axi._name + '.range[0]'] = axi.range[0];
- aobj[axi._name + '.range[1]'] = axi.range[1];
-
- axi.range = axi._r.slice();
- }
-
- return Plotly.relayout(gd, aobj).then(function() {
- for(var i = 0; i < affectedSubplots.length; i++) {
- unsetSubplotTransform(affectedSubplots[i]);
- }
- });
- }
+ return Plotly.relayout(gd, aobj).then(function () {
+ for (var i = 0; i < affectedSubplots.length; i++) {
+ unsetSubplotTransform(affectedSubplots[i])
+ }
+ })
+ }
- var t1, t2, raf;
- var easeFn = d3.ease(transitionOpts.easing);
+ var t1, t2, raf
+ var easeFn = d3.ease(transitionOpts.easing)
- gd._transitionData._interruptCallbacks.push(function() {
- window.cancelAnimationFrame(raf);
- raf = null;
- return transitionInterrupt();
- });
+ gd._transitionData._interruptCallbacks.push(function () {
+ window.cancelAnimationFrame(raf)
+ raf = null
+ return transitionInterrupt()
+ })
- function doFrame() {
- t2 = Date.now();
+ function doFrame () {
+ t2 = Date.now()
- var tInterp = Math.min(1, (t2 - t1) / transitionOpts.duration);
- var progress = easeFn(tInterp);
+ var tInterp = Math.min(1, (t2 - t1) / transitionOpts.duration)
+ var progress = easeFn(tInterp)
- for(var i = 0; i < affectedSubplots.length; i++) {
- updateSubplot(affectedSubplots[i], progress);
- }
+ for (var i = 0; i < affectedSubplots.length; i++) {
+ updateSubplot(affectedSubplots[i], progress)
+ }
- if(t2 - t1 > transitionOpts.duration) {
- transitionComplete();
- raf = window.cancelAnimationFrame(doFrame);
- } else {
- raf = window.requestAnimationFrame(doFrame);
- }
+ if (t2 - t1 > transitionOpts.duration) {
+ transitionComplete()
+ raf = window.cancelAnimationFrame(doFrame)
+ } else {
+ raf = window.requestAnimationFrame(doFrame)
}
+ }
- t1 = Date.now();
- raf = window.requestAnimationFrame(doFrame);
+ t1 = Date.now()
+ raf = window.requestAnimationFrame(doFrame)
- return Promise.resolve();
-};
+ return Promise.resolve()
+}
diff --git a/src/plots/command.js b/src/plots/command.js
index 62c060edd5e..3fd3e78a02a 100644
--- a/src/plots/command.js
+++ b/src/plots/command.js
@@ -6,11 +6,10 @@
* LICENSE file in the root directory of this source tree.
*/
+'use strict'
-'use strict';
-
-var Plotly = require('../plotly');
-var Lib = require('../lib');
+var Plotly = require('../plotly')
+var Lib = require('../lib')
/*
* Create or update an observer. This function is designed to be
@@ -28,112 +27,110 @@ var Lib = require('../lib');
* A listener called when the value is changed. Receives data object
* with information about the new state.
*/
-exports.manageCommandObserver = function(gd, container, commandList, onchange) {
- var ret = {};
- var enabled = true;
+exports.manageCommandObserver = function (gd, container, commandList, onchange) {
+ var ret = {}
+ var enabled = true
- if(container && container._commandObserver) {
- ret = container._commandObserver;
- }
+ if (container && container._commandObserver) {
+ ret = container._commandObserver
+ }
- if(!ret.cache) {
- ret.cache = {};
- }
+ if (!ret.cache) {
+ ret.cache = {}
+ }
// Either create or just recompute this:
- ret.lookupTable = {};
+ ret.lookupTable = {}
- var binding = exports.hasSimpleAPICommandBindings(gd, commandList, ret.lookupTable);
+ var binding = exports.hasSimpleAPICommandBindings(gd, commandList, ret.lookupTable)
- if(container && container._commandObserver) {
- if(!binding) {
+ if (container && container._commandObserver) {
+ if (!binding) {
// If container exists and there are no longer any bindings,
// remove existing:
- if(container._commandObserver.remove) {
- container._commandObserver.remove();
- container._commandObserver = null;
- return ret;
- }
- } else {
+ if (container._commandObserver.remove) {
+ container._commandObserver.remove()
+ container._commandObserver = null
+ return ret
+ }
+ } else {
// If container exists and there *are* bindings, then the lookup
// table should have been updated and check is already attached,
// so there's nothing to be done:
- return ret;
-
-
- }
+ return ret
}
+ }
// Determine whether there's anything to do for this binding:
- if(binding) {
+ if (binding) {
// Build the cache:
- bindingValueHasChanged(gd, binding, ret.cache);
+ bindingValueHasChanged(gd, binding, ret.cache)
- ret.check = function check() {
- if(!enabled) return;
+ ret.check = function check () {
+ if (!enabled) return
- var update = bindingValueHasChanged(gd, binding, ret.cache);
+ var update = bindingValueHasChanged(gd, binding, ret.cache)
- if(update.changed && onchange) {
+ if (update.changed && onchange) {
// Disable checks for the duration of this command in order to avoid
// infinite loops:
- if(ret.lookupTable[update.value] !== undefined) {
- ret.disable();
- Promise.resolve(onchange({
- value: update.value,
- type: binding.type,
- prop: binding.prop,
- traces: binding.traces,
- index: ret.lookupTable[update.value]
- })).then(ret.enable, ret.enable);
- }
- }
-
- return update.changed;
- };
+ if (ret.lookupTable[update.value] !== undefined) {
+ ret.disable()
+ Promise.resolve(onchange({
+ value: update.value,
+ type: binding.type,
+ prop: binding.prop,
+ traces: binding.traces,
+ index: ret.lookupTable[update.value]
+ })).then(ret.enable, ret.enable)
+ }
+ }
- var checkEvents = [
- 'plotly_relayout',
- 'plotly_redraw',
- 'plotly_restyle',
- 'plotly_update',
- 'plotly_animatingframe',
- 'plotly_afterplot'
- ];
+ return update.changed
+ }
- for(var i = 0; i < checkEvents.length; i++) {
- gd._internalOn(checkEvents[i], ret.check);
- }
+ var checkEvents = [
+ 'plotly_relayout',
+ 'plotly_redraw',
+ 'plotly_restyle',
+ 'plotly_update',
+ 'plotly_animatingframe',
+ 'plotly_afterplot'
+ ]
+
+ for (var i = 0; i < checkEvents.length; i++) {
+ gd._internalOn(checkEvents[i], ret.check)
+ }
- ret.remove = function() {
- for(var i = 0; i < checkEvents.length; i++) {
- gd._removeInternalListener(checkEvents[i], ret.check);
- }
- };
- } else {
+ ret.remove = function () {
+ for (var i = 0; i < checkEvents.length; i++) {
+ gd._removeInternalListener(checkEvents[i], ret.check)
+ }
+ }
+ } else {
// TODO: It'd be really neat to actually give a *reason* for this, but at least a warning
// is a start
- Lib.warn('Unable to automatically bind plot updates to API command');
+ Lib.warn('Unable to automatically bind plot updates to API command')
- ret.lookupTable = {};
- ret.remove = function() {};
- }
+ ret.lookupTable = {}
+ ret.remove = function () {}
+ }
- ret.disable = function disable() {
- enabled = false;
- };
+ ret.disable = function disable () {
+ enabled = false
+ }
- ret.enable = function enable() {
- enabled = true;
- };
+ ret.enable = function enable () {
+ enabled = true
+ }
- if(container) {
- container._commandObserver = ret;
- }
+ if (container) {
+ container._commandObserver = ret
+ }
- return ret;
-};
+ return ret
+}
/*
* This function checks to see if an array of objects containing
@@ -144,108 +141,108 @@ exports.manageCommandObserver = function(gd, container, commandList, onchange) {
* 2. only one property may be affected
* 3. the same property must be affected by all commands
*/
-exports.hasSimpleAPICommandBindings = function(gd, commandList, bindingsByValue) {
- var i;
- var n = commandList.length;
+exports.hasSimpleAPICommandBindings = function (gd, commandList, bindingsByValue) {
+ var i
+ var n = commandList.length
- var refBinding;
+ var refBinding
- for(i = 0; i < n; i++) {
- var binding;
- var command = commandList[i];
- var method = command.method;
- var args = command.args;
+ for (i = 0; i < n; i++) {
+ var binding
+ var command = commandList[i]
+ var method = command.method
+ var args = command.args
// If any command has no method, refuse to bind:
- if(!method) {
- return false;
- }
- var bindings = exports.computeAPICommandBindings(gd, method, args);
+ if (!method) {
+ return false
+ }
+ var bindings = exports.computeAPICommandBindings(gd, method, args)
// Right now, handle one and *only* one property being set:
- if(bindings.length !== 1) {
- return false;
- }
+ if (bindings.length !== 1) {
+ return false
+ }
- if(!refBinding) {
- refBinding = bindings[0];
- if(Array.isArray(refBinding.traces)) {
- refBinding.traces.sort();
+ if (!refBinding) {
+ refBinding = bindings[0]
+ if (Array.isArray(refBinding.traces)) {
+ refBinding.traces.sort()
+ }
+ } else {
+ binding = bindings[0]
+ if (binding.type !== refBinding.type) {
+ return false
+ }
+ if (binding.prop !== refBinding.prop) {
+ return false
+ }
+ if (Array.isArray(refBinding.traces)) {
+ if (Array.isArray(binding.traces)) {
+ binding.traces.sort()
+ for (var j = 0; j < refBinding.traces.length; j++) {
+ if (refBinding.traces[j] !== binding.traces[j]) {
+ return false
}
+ }
} else {
- binding = bindings[0];
- if(binding.type !== refBinding.type) {
- return false;
- }
- if(binding.prop !== refBinding.prop) {
- return false;
- }
- if(Array.isArray(refBinding.traces)) {
- if(Array.isArray(binding.traces)) {
- binding.traces.sort();
- for(var j = 0; j < refBinding.traces.length; j++) {
- if(refBinding.traces[j] !== binding.traces[j]) {
- return false;
- }
- }
- } else {
- return false;
- }
- } else {
- if(binding.prop !== refBinding.prop) {
- return false;
- }
- }
- }
-
- binding = bindings[0];
- var value = binding.value;
- if(Array.isArray(value)) {
- if(value.length === 1) {
- value = value[0];
- } else {
- return false;
- }
+ return false
}
- if(bindingsByValue) {
- bindingsByValue[value] = i;
+ } else {
+ if (binding.prop !== refBinding.prop) {
+ return false
}
+ }
}
- return refBinding;
-};
+ binding = bindings[0]
+ var value = binding.value
+ if (Array.isArray(value)) {
+ if (value.length === 1) {
+ value = value[0]
+ } else {
+ return false
+ }
+ }
+ if (bindingsByValue) {
+ bindingsByValue[value] = i
+ }
+ }
+
+ return refBinding
+}
-function bindingValueHasChanged(gd, binding, cache) {
- var container, value, obj;
- var changed = false;
+function bindingValueHasChanged (gd, binding, cache) {
+ var container, value, obj
+ var changed = false
- if(binding.type === 'data') {
+ if (binding.type === 'data') {
// If it's data, we need to get a trace. Based on the limited scope
// of what we cover, we can just take the first trace from the list,
// or otherwise just the first trace:
- container = gd._fullData[binding.traces !== null ? binding.traces[0] : 0];
- } else if(binding.type === 'layout') {
- container = gd._fullLayout;
- } else {
- return false;
- }
+ container = gd._fullData[binding.traces !== null ? binding.traces[0] : 0]
+ } else if (binding.type === 'layout') {
+ container = gd._fullLayout
+ } else {
+ return false
+ }
- value = Lib.nestedProperty(container, binding.prop).get();
+ value = Lib.nestedProperty(container, binding.prop).get()
- obj = cache[binding.type] = cache[binding.type] || {};
+ obj = cache[binding.type] = cache[binding.type] || {}
- if(obj.hasOwnProperty(binding.prop)) {
- if(obj[binding.prop] !== value) {
- changed = true;
- }
+ if (obj.hasOwnProperty(binding.prop)) {
+ if (obj[binding.prop] !== value) {
+ changed = true
}
+ }
- obj[binding.prop] = value;
+ obj[binding.prop] = value
- return {
- changed: changed,
- value: value
- };
+ return {
+ changed: changed,
+ value: value
+ }
}
/*
@@ -259,157 +256,157 @@ function bindingValueHasChanged(gd, binding, cache) {
* @param {array} args
* A list of arguments passed to the API command
*/
-exports.executeAPICommand = function(gd, method, args) {
- var apiMethod = Plotly[method];
-
- var allArgs = [gd];
- for(var i = 0; i < args.length; i++) {
- allArgs.push(args[i]);
- }
+exports.executeAPICommand = function (gd, method, args) {
+ var apiMethod = Plotly[method]
+
+ var allArgs = [gd]
+ for (var i = 0; i < args.length; i++) {
+ allArgs.push(args[i])
+ }
+
+ return apiMethod.apply(null, allArgs).catch(function (err) {
+ Lib.warn('API call to Plotly.' + method + ' rejected.', err)
+ return Promise.reject(err)
+ })
+}
- return apiMethod.apply(null, allArgs).catch(function(err) {
- Lib.warn('API call to Plotly.' + method + ' rejected.', err);
- return Promise.reject(err);
- });
-};
-
-exports.computeAPICommandBindings = function(gd, method, args) {
- var bindings;
- switch(method) {
- case 'restyle':
- bindings = computeDataBindings(gd, args);
- break;
- case 'relayout':
- bindings = computeLayoutBindings(gd, args);
- break;
- case 'update':
- bindings = computeDataBindings(gd, [args[0], args[2]])
- .concat(computeLayoutBindings(gd, [args[1]]));
- break;
- case 'animate':
- bindings = computeAnimateBindings(gd, args);
- break;
- default:
+exports.computeAPICommandBindings = function (gd, method, args) {
+ var bindings
+ switch (method) {
+ case 'restyle':
+ bindings = computeDataBindings(gd, args)
+ break
+ case 'relayout':
+ bindings = computeLayoutBindings(gd, args)
+ break
+ case 'update':
+ bindings = computeDataBindings(gd, [args[0], args[2]])
+ .concat(computeLayoutBindings(gd, [args[1]]))
+ break
+ case 'animate':
+ bindings = computeAnimateBindings(gd, args)
+ break
+ default:
// This is the case where intelligent logic about what affects
// this command is not implemented. It causes no ill effects.
// For example, addFrames simply won't bind to a control component.
- bindings = [];
- }
- return bindings;
-};
+ bindings = []
+ }
+ return bindings
+}
-function computeAnimateBindings(gd, args) {
+function computeAnimateBindings (gd, args) {
// We'll assume that the only relevant modification an animation
// makes that's meaningfully tracked is the frame:
- if(Array.isArray(args[0]) && args[0].length === 1 && ['string', 'number'].indexOf(typeof args[0][0]) !== -1) {
- return [{type: 'layout', prop: '_currentFrame', value: args[0][0].toString()}];
- } else {
- return [];
- }
+ if (Array.isArray(args[0]) && args[0].length === 1 && ['string', 'number'].indexOf(typeof args[0][0]) !== -1) {
+ return [{type: 'layout', prop: '_currentFrame', value: args[0][0].toString()}]
+ } else {
+ return []
+ }
}
-function computeLayoutBindings(gd, args) {
- var bindings = [];
+function computeLayoutBindings (gd, args) {
+ var bindings = []
- var astr = args[0];
- var aobj = {};
- if(typeof astr === 'string') {
- aobj[astr] = args[1];
- } else if(Lib.isPlainObject(astr)) {
- aobj = astr;
- } else {
- return bindings;
- }
+ var astr = args[0]
+ var aobj = {}
+ if (typeof astr === 'string') {
+ aobj[astr] = args[1]
+ } else if (Lib.isPlainObject(astr)) {
+ aobj = astr
+ } else {
+ return bindings
+ }
- crawl(aobj, function(path, attrName, attr) {
- bindings.push({type: 'layout', prop: path, value: attr});
- }, '', 0);
+ crawl(aobj, function (path, attrName, attr) {
+ bindings.push({type: 'layout', prop: path, value: attr})
+ }, '', 0)
- return bindings;
+ return bindings
}
-function computeDataBindings(gd, args) {
- var traces, astr, val, aobj;
- var bindings = [];
+function computeDataBindings (gd, args) {
+ var traces, astr, val, aobj
+ var bindings = []
// Logic copied from Plotly.restyle:
- astr = args[0];
- val = args[1];
- traces = args[2];
- aobj = {};
- if(typeof astr === 'string') {
- aobj[astr] = val;
- } else if(Lib.isPlainObject(astr)) {
+ astr = args[0]
+ val = args[1]
+ traces = args[2]
+ aobj = {}
+ if (typeof astr === 'string') {
+ aobj[astr] = val
+ } else if (Lib.isPlainObject(astr)) {
// the 3-arg form
- aobj = astr;
+ aobj = astr
- if(traces === undefined) {
- traces = val;
- }
- } else {
- return bindings;
+ if (traces === undefined) {
+ traces = val
}
+ } else {
+ return bindings
+ }
- if(traces === undefined) {
+ if (traces === undefined) {
// Explicitly assign this to null instead of undefined:
- traces = null;
+ traces = null
+ }
+
+ crawl(aobj, function (path, attrName, attr) {
+ var thisTraces
+ if (Array.isArray(attr)) {
+ var nAttr = Math.min(attr.length, gd.data.length)
+ if (traces) {
+ nAttr = Math.min(nAttr, traces.length)
+ }
+ thisTraces = []
+ for (var j = 0; j < nAttr; j++) {
+ thisTraces[j] = traces ? traces[j] : j
+ }
+ } else {
+ thisTraces = traces ? traces.slice(0) : null
}
- crawl(aobj, function(path, attrName, attr) {
- var thisTraces;
- if(Array.isArray(attr)) {
- var nAttr = Math.min(attr.length, gd.data.length);
- if(traces) {
- nAttr = Math.min(nAttr, traces.length);
- }
- thisTraces = [];
- for(var j = 0; j < nAttr; j++) {
- thisTraces[j] = traces ? traces[j] : j;
- }
- } else {
- thisTraces = traces ? traces.slice(0) : null;
- }
-
// Convert [7] to just 7 when traces is null:
- if(thisTraces === null) {
- if(Array.isArray(attr)) {
- attr = attr[0];
- }
- } else if(Array.isArray(thisTraces)) {
- if(!Array.isArray(attr)) {
- var tmp = attr;
- attr = [];
- for(var i = 0; i < thisTraces.length; i++) {
- attr[i] = tmp;
- }
- }
- attr.length = Math.min(thisTraces.length, attr.length);
+ if (thisTraces === null) {
+ if (Array.isArray(attr)) {
+ attr = attr[0]
+ }
+ } else if (Array.isArray(thisTraces)) {
+ if (!Array.isArray(attr)) {
+ var tmp = attr
+ attr = []
+ for (var i = 0; i < thisTraces.length; i++) {
+ attr[i] = tmp
}
+ }
+ attr.length = Math.min(thisTraces.length, attr.length)
+ }
- bindings.push({
- type: 'data',
- prop: path,
- traces: thisTraces,
- value: attr
- });
- }, '', 0);
+ bindings.push({
+ type: 'data',
+ prop: path,
+ traces: thisTraces,
+ value: attr
+ })
+ }, '', 0)
- return bindings;
+ return bindings
}
-function crawl(attrs, callback, path, depth) {
- Object.keys(attrs).forEach(function(attrName) {
- var attr = attrs[attrName];
+function crawl (attrs, callback, path, depth) {
+ Object.keys(attrs).forEach(function (attrName) {
+ var attr = attrs[attrName]
- if(attrName[0] === '_') return;
+ if (attrName[0] === '_') return
- var thisPath = path + (depth > 0 ? '.' : '') + attrName;
+ var thisPath = path + (depth > 0 ? '.' : '') + attrName
- if(Lib.isPlainObject(attr)) {
- crawl(attr, callback, thisPath, depth + 1);
- } else {
+ if (Lib.isPlainObject(attr)) {
+ crawl(attr, callback, thisPath, depth + 1)
+ } else {
// Only execute the callback on leaf nodes:
- callback(thisPath, attrName, attr);
- }
- });
+ callback(thisPath, attrName, attr)
+ }
+ })
}
diff --git a/src/plots/font_attributes.js b/src/plots/font_attributes.js
index daf2490c563..d3ad9364ba7 100644
--- a/src/plots/font_attributes.js
+++ b/src/plots/font_attributes.js
@@ -6,35 +6,34 @@
* LICENSE file in the root directory of this source tree.
*/
-'use strict';
-
+'use strict'
module.exports = {
- family: {
- valType: 'string',
- role: 'style',
- noBlank: true,
- strict: true,
- description: [
- 'HTML font family - the typeface that will be applied by the web browser.',
- 'The web browser will only be able to apply a font if it is available on the system',
- 'which it operates. Provide multiple font families, separated by commas, to indicate',
- 'the preference in which to apply fonts if they aren\'t available on the system.',
- 'The plotly service (at https://plot.ly or on-premise) generates images on a server,',
- 'where only a select number of',
- 'fonts are installed and supported.',
- 'These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*,',
- '*Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*,',
- '*PT Sans Narrow*, *Raleway*, *Times New Roman*.'
- ].join(' ')
- },
- size: {
- valType: 'number',
- role: 'style',
- min: 1
- },
- color: {
- valType: 'color',
- role: 'style'
- }
-};
+ family: {
+ valType: 'string',
+ role: 'style',
+ noBlank: true,
+ strict: true,
+ description: [
+ 'HTML font family - the typeface that will be applied by the web browser.',
+ 'The web browser will only be able to apply a font if it is available on the system',
+ 'which it operates. Provide multiple font families, separated by commas, to indicate',
+ 'the preference in which to apply fonts if they aren\'t available on the system.',
+ 'The plotly service (at https://plot.ly or on-premise) generates images on a server,',
+ 'where only a select number of',
+ 'fonts are installed and supported.',
+ 'These include *Arial*, *Balto*, *Courier New*, *Droid Sans*,, *Droid Serif*,',
+ '*Droid Sans Mono*, *Gravitas One*, *Old Standard TT*, *Open Sans*, *Overpass*,',
+ '*PT Sans Narrow*, *Raleway*, *Times New Roman*.'
+ ].join(' ')
+ },
+ size: {
+ valType: 'number',
+ role: 'style',
+ min: 1
+ },
+ color: {
+ valType: 'color',
+ role: 'style'
+ }
+}
diff --git a/src/plots/frame_attributes.js b/src/plots/frame_attributes.js
index cfb57e1b689..c06d2b1a4f0 100644
--- a/src/plots/frame_attributes.js
+++ b/src/plots/frame_attributes.js
@@ -6,55 +6,55 @@
* LICENSE file in the root directory of this source tree.
*/
-'use strict';
+'use strict'
module.exports = {
- _isLinkedToArray: 'frames_entry',
+ _isLinkedToArray: 'frames_entry',
- group: {
- valType: 'string',
- role: 'info',
- description: [
- 'An identifier that specifies the group to which the frame belongs,',
- 'used by animate to select a subset of frames.'
- ].join(' ')
- },
- name: {
- valType: 'string',
- role: 'info',
- description: 'A label by which to identify the frame'
- },
- traces: {
- valType: 'any',
- role: 'info',
- description: [
- 'A list of trace indices that identify the respective traces in the',
- 'data attribute'
- ].join(' ')
- },
- baseframe: {
- valType: 'string',
- role: 'info',
- description: [
- 'The name of the frame into which this frame\'s properties are merged',
- 'before applying. This is used to unify properties and avoid needing',
- 'to specify the same values for the same properties in multiple frames.'
- ].join(' ')
- },
- data: {
- valType: 'any',
- role: 'object',
- description: [
- 'A list of traces this frame modifies. The format is identical to the',
- 'normal trace definition.'
- ].join(' ')
- },
- layout: {
- valType: 'any',
- role: 'object',
- description: [
- 'Layout properties which this frame modifies. The format is identical',
- 'to the normal layout definition.'
- ].join(' ')
- }
-};
+ group: {
+ valType: 'string',
+ role: 'info',
+ description: [
+ 'An identifier that specifies the group to which the frame belongs,',
+ 'used by animate to select a subset of frames.'
+ ].join(' ')
+ },
+ name: {
+ valType: 'string',
+ role: 'info',
+ description: 'A label by which to identify the frame'
+ },
+ traces: {
+ valType: 'any',
+ role: 'info',
+ description: [
+ 'A list of trace indices that identify the respective traces in the',
+ 'data attribute'
+ ].join(' ')
+ },
+ baseframe: {
+ valType: 'string',
+ role: 'info',
+ description: [
+ 'The name of the frame into which this frame\'s properties are merged',
+ 'before applying. This is used to unify properties and avoid needing',
+ 'to specify the same values for the same properties in multiple frames.'
+ ].join(' ')
+ },
+ data: {
+ valType: 'any',
+ role: 'object',
+ description: [
+ 'A list of traces this frame modifies. The format is identical to the',
+ 'normal trace definition.'
+ ].join(' ')
+ },
+ layout: {
+ valType: 'any',
+ role: 'object',
+ description: [
+ 'Layout properties which this frame modifies. The format is identical',
+ 'to the normal layout definition.'
+ ].join(' ')
+ }
+}
diff --git a/src/plots/geo/constants.js b/src/plots/geo/constants.js
index 92564b4e485..bd74a8744c8 100644
--- a/src/plots/geo/constants.js
+++ b/src/plots/geo/constants.js
@@ -6,151 +6,150 @@
* LICENSE file in the root directory of this source tree.
*/
+'use strict'
-'use strict';
-
-var params = module.exports = {};
+var params = module.exports = {}
// projection names to d3 function name
params.projNames = {
// d3.geo.projection
- 'equirectangular': 'equirectangular',
- 'mercator': 'mercator',
- 'orthographic': 'orthographic',
- 'natural earth': 'naturalEarth',
- 'kavrayskiy7': 'kavrayskiy7',
- 'miller': 'miller',
- 'robinson': 'robinson',
- 'eckert4': 'eckert4',
- 'azimuthal equal area': 'azimuthalEqualArea',
- 'azimuthal equidistant': 'azimuthalEquidistant',
- 'conic equal area': 'conicEqualArea',
- 'conic conformal': 'conicConformal',
- 'conic equidistant': 'conicEquidistant',
- 'gnomonic': 'gnomonic',
- 'stereographic': 'stereographic',
- 'mollweide': 'mollweide',
- 'hammer': 'hammer',
- 'transverse mercator': 'transverseMercator',
- 'albers usa': 'albersUsa',
- 'winkel tripel': 'winkel3'
-};
+ 'equirectangular': 'equirectangular',
+ 'mercator': 'mercator',
+ 'orthographic': 'orthographic',
+ 'natural earth': 'naturalEarth',
+ 'kavrayskiy7': 'kavrayskiy7',
+ 'miller': 'miller',
+ 'robinson': 'robinson',
+ 'eckert4': 'eckert4',
+ 'azimuthal equal area': 'azimuthalEqualArea',
+ 'azimuthal equidistant': 'azimuthalEquidistant',
+ 'conic equal area': 'conicEqualArea',
+ 'conic conformal': 'conicConformal',
+ 'conic equidistant': 'conicEquidistant',
+ 'gnomonic': 'gnomonic',
+ 'stereographic': 'stereographic',
+ 'mollweide': 'mollweide',
+ 'hammer': 'hammer',
+ 'transverse mercator': 'transverseMercator',
+ 'albers usa': 'albersUsa',
+ 'winkel tripel': 'winkel3'
+}
// name of the axes
-params.axesNames = ['lonaxis', 'lataxis'];
+params.axesNames = ['lonaxis', 'lataxis']
// max longitudinal angular span (EXPERIMENTAL)
params.lonaxisSpan = {
- 'orthographic': 180,
- 'azimuthal equal area': 360,
- 'azimuthal equidistant': 360,
- 'conic conformal': 180,
- 'gnomonic': 160,
- 'stereographic': 180,
- 'transverse mercator': 180,
- '*': 360
-};
+ 'orthographic': 180,
+ 'azimuthal equal area': 360,
+ 'azimuthal equidistant': 360,
+ 'conic conformal': 180,
+ 'gnomonic': 160,
+ 'stereographic': 180,
+ 'transverse mercator': 180,
+ '*': 360
+}
// max latitudinal angular span (EXPERIMENTAL)
params.lataxisSpan = {
- 'conic conformal': 150,
- 'stereographic': 179.5,
- '*': 180
-};
+ 'conic conformal': 150,
+ 'stereographic': 179.5,
+ '*': 180
+}
// defaults for each scope
params.scopeDefaults = {
- world: {
- lonaxisRange: [-180, 180],
- lataxisRange: [-90, 90],
- projType: 'equirectangular',
- projRotate: [0, 0, 0]
- },
- usa: {
- lonaxisRange: [-180, -50],
- lataxisRange: [15, 80],
- projType: 'albers usa'
- },
- europe: {
- lonaxisRange: [-30, 60],
- lataxisRange: [30, 80],
- projType: 'conic conformal',
- projRotate: [15, 0, 0],
- projParallels: [0, 60]
- },
- asia: {
- lonaxisRange: [22, 160],
- lataxisRange: [-15, 55],
- projType: 'mercator',
- projRotate: [0, 0, 0]
- },
- africa: {
- lonaxisRange: [-30, 60],
- lataxisRange: [-40, 40],
- projType: 'mercator',
- projRotate: [0, 0, 0]
- },
- 'north america': {
- lonaxisRange: [-180, -45],
- lataxisRange: [5, 85],
- projType: 'conic conformal',
- projRotate: [-100, 0, 0],
- projParallels: [29.5, 45.5]
- },
- 'south america': {
- lonaxisRange: [-100, -30],
- lataxisRange: [-60, 15],
- projType: 'mercator',
- projRotate: [0, 0, 0]
- }
-};
+ world: {
+ lonaxisRange: [-180, 180],
+ lataxisRange: [-90, 90],
+ projType: 'equirectangular',
+ projRotate: [0, 0, 0]
+ },
+ usa: {
+ lonaxisRange: [-180, -50],
+ lataxisRange: [15, 80],
+ projType: 'albers usa'
+ },
+ europe: {
+ lonaxisRange: [-30, 60],
+ lataxisRange: [30, 80],
+ projType: 'conic conformal',
+ projRotate: [15, 0, 0],
+ projParallels: [0, 60]
+ },
+ asia: {
+ lonaxisRange: [22, 160],
+ lataxisRange: [-15, 55],
+ projType: 'mercator',
+ projRotate: [0, 0, 0]
+ },
+ africa: {
+ lonaxisRange: [-30, 60],
+ lataxisRange: [-40, 40],
+ projType: 'mercator',
+ projRotate: [0, 0, 0]
+ },
+ 'north america': {
+ lonaxisRange: [-180, -45],
+ lataxisRange: [5, 85],
+ projType: 'conic conformal',
+ projRotate: [-100, 0, 0],
+ projParallels: [29.5, 45.5]
+ },
+ 'south america': {
+ lonaxisRange: [-100, -30],
+ lataxisRange: [-60, 15],
+ projType: 'mercator',
+ projRotate: [0, 0, 0]
+ }
+}
// angular pad to avoid rounding error around clip angles
-params.clipPad = 1e-3;
+params.clipPad = 1e-3
// map projection precision
-params.precision = 0.1;
+params.precision = 0.1
// default land and water fill colors
-params.landColor = '#F0DC82';
-params.waterColor = '#3399FF';
+params.landColor = '#F0DC82'
+params.waterColor = '#3399FF'
// locationmode to layer name
params.locationmodeToLayer = {
- 'ISO-3': 'countries',
- 'USA-states': 'subunits',
- 'country names': 'countries'
-};
+ 'ISO-3': 'countries',
+ 'USA-states': 'subunits',
+ 'country names': 'countries'
+}
// SVG element for a sphere (use to frame maps)
-params.sphereSVG = {type: 'Sphere'};
+params.sphereSVG = {type: 'Sphere'}
// N.B. base layer names must be the same as in the topojson files
// base layer with a fill color
-params.fillLayers = ['ocean', 'land', 'lakes'];
+params.fillLayers = ['ocean', 'land', 'lakes']
// base layer with a only a line color
-params.lineLayers = ['subunits', 'countries', 'coastlines', 'rivers', 'frame'];
+params.lineLayers = ['subunits', 'countries', 'coastlines', 'rivers', 'frame']
// all base layers - in order
params.baseLayers = [
- 'ocean', 'land', 'lakes',
- 'subunits', 'countries', 'coastlines', 'rivers',
- 'lataxis', 'lonaxis',
- 'frame'
-];
+ 'ocean', 'land', 'lakes',
+ 'subunits', 'countries', 'coastlines', 'rivers',
+ 'lataxis', 'lonaxis',
+ 'frame'
+]
params.layerNameToAdjective = {
- ocean: 'ocean',
- land: 'land',
- lakes: 'lake',
- subunits: 'subunit',
- countries: 'country',
- coastlines: 'coastline',
- rivers: 'river',
- frame: 'frame'
-};
+ ocean: 'ocean',
+ land: 'land',
+ lakes: 'lake',
+ subunits: 'subunit',
+ countries: 'country',
+ coastlines: 'coastline',
+ rivers: 'river',
+ frame: 'frame'
+}
// base layers drawn over choropleth
-params.baseLayersOverChoropleth = ['rivers', 'lakes'];
+params.baseLayersOverChoropleth = ['rivers', 'lakes']
diff --git a/src/plots/geo/geo.js b/src/plots/geo/geo.js
index 75bd8e37261..e52f1c14ea8 100644
--- a/src/plots/geo/geo.js
+++ b/src/plots/geo/geo.js
@@ -6,231 +6,224 @@
* LICENSE file in the root directory of this source tree.
*/
-
-'use strict';
+'use strict'
/* global PlotlyGeoAssets:false */
-var d3 = require('d3');
+var d3 = require('d3')
-var Color = require('../../components/color');
-var Drawing = require('../../components/drawing');
-var Plots = require('../plots');
-var Axes = require('../cartesian/axes');
-var Fx = require('../cartesian/graph_interact');
+var Color = require('../../components/color')
+var Drawing = require('../../components/drawing')
+var Plots = require('../plots')
+var Axes = require('../cartesian/axes')
+var Fx = require('../cartesian/graph_interact')
-var addProjectionsToD3 = require('./projections');
-var createGeoScale = require('./set_scale');
-var createGeoZoom = require('./zoom');
-var createGeoZoomReset = require('./zoom_reset');
-var constants = require('./constants');
+var addProjectionsToD3 = require('./projections')
+var createGeoScale = require('./set_scale')
+var createGeoZoom = require('./zoom')
+var createGeoZoomReset = require('./zoom_reset')
+var constants = require('./constants')
-var xmlnsNamespaces = require('../../constants/xmlns_namespaces');
-var topojsonUtils = require('../../lib/topojson_utils');
-var topojsonFeature = require('topojson-client').feature;
+var xmlnsNamespaces = require('../../constants/xmlns_namespaces')
+var topojsonUtils = require('../../lib/topojson_utils')
+var topojsonFeature = require('topojson-client').feature
// add a few projection types to d3.geo
-addProjectionsToD3(d3);
-
+addProjectionsToD3(d3)
-function Geo(options, fullLayout) {
- this.id = options.id;
- this.graphDiv = options.graphDiv;
- this.container = options.container;
- this.topojsonURL = options.topojsonURL;
+function Geo (options, fullLayout) {
+ this.id = options.id
+ this.graphDiv = options.graphDiv
+ this.container = options.container
+ this.topojsonURL = options.topojsonURL
- this.hoverContainer = null;
+ this.hoverContainer = null
- this.topojsonName = null;
- this.topojson = null;
+ this.topojsonName = null
+ this.topojson = null
- this.projectionType = null;
- this.projection = null;
+ this.projectionType = null
+ this.projection = null
- this.clipAngle = null;
- this.setScale = null;
- this.path = null;
+ this.clipAngle = null
+ this.setScale = null
+ this.path = null
- this.zoom = null;
- this.zoomReset = null;
+ this.zoom = null
+ this.zoomReset = null
- this.xaxis = null;
- this.yaxis = null;
+ this.xaxis = null
+ this.yaxis = null
- this.makeFramework();
- this.updateFx(fullLayout.hovermode);
+ this.makeFramework()
+ this.updateFx(fullLayout.hovermode)
- this.traceHash = {};
+ this.traceHash = {}
}
-module.exports = Geo;
+module.exports = Geo
-var proto = Geo.prototype;
+var proto = Geo.prototype
-proto.plot = function(geoCalcData, fullLayout, promises) {
- var _this = this,
- geoLayout = fullLayout[_this.id],
- graphSize = fullLayout._size;
+proto.plot = function (geoCalcData, fullLayout, promises) {
+ var _this = this,
+ geoLayout = fullLayout[_this.id],
+ graphSize = fullLayout._size
- var topojsonNameNew, topojsonPath;
+ var topojsonNameNew, topojsonPath
// N.B. 'geoLayout' is unambiguous, no need for 'user' geo layout here
// TODO don't reset projection on all graph edits
- _this.projection = null;
+ _this.projection = null
- _this.setScale = createGeoScale(geoLayout, graphSize);
- _this.makeProjection(geoLayout);
- _this.makePath();
- _this.adjustLayout(geoLayout, graphSize);
+ _this.setScale = createGeoScale(geoLayout, graphSize)
+ _this.makeProjection(geoLayout)
+ _this.makePath()
+ _this.adjustLayout(geoLayout, graphSize)
- _this.zoom = createGeoZoom(_this, geoLayout);
- _this.zoomReset = createGeoZoomReset(_this, geoLayout);
- _this.mockAxis = createMockAxis(fullLayout);
+ _this.zoom = createGeoZoom(_this, geoLayout)
+ _this.zoomReset = createGeoZoomReset(_this, geoLayout)
+ _this.mockAxis = createMockAxis(fullLayout)
- _this.framework
+ _this.framework
.call(_this.zoom)
- .on('dblclick.zoom', _this.zoomReset);
+ .on('dblclick.zoom', _this.zoomReset)
- _this.framework.on('mousemove', function() {
- var mouse = d3.mouse(this),
- lonlat = _this.projection.invert(mouse);
+ _this.framework.on('mousemove', function () {
+ var mouse = d3.mouse(this),
+ lonlat = _this.projection.invert(mouse)
- if(isNaN(lonlat[0]) || isNaN(lonlat[1])) return;
+ if (isNaN(lonlat[0]) || isNaN(lonlat[1])) return
- var evt = {
- target: true,
- xpx: mouse[0],
- ypx: mouse[1]
- };
+ var evt = {
+ target: true,
+ xpx: mouse[0],
+ ypx: mouse[1]
+ }
- _this.xaxis.c2p = function() { return mouse[0]; };
- _this.xaxis.p2c = function() { return lonlat[0]; };
- _this.yaxis.c2p = function() { return mouse[1]; };
- _this.yaxis.p2c = function() { return lonlat[1]; };
+ _this.xaxis.c2p = function () { return mouse[0] }
+ _this.xaxis.p2c = function () { return lonlat[0] }
+ _this.yaxis.c2p = function () { return mouse[1] }
+ _this.yaxis.p2c = function () { return lonlat[1] }
- Fx.hover(_this.graphDiv, evt, _this.id);
- });
+ Fx.hover(_this.graphDiv, evt, _this.id)
+ })
- _this.framework.on('mouseout', function() {
- Fx.loneUnhover(fullLayout._toppaper);
- });
+ _this.framework.on('mouseout', function () {
+ Fx.loneUnhover(fullLayout._toppaper)
+ })
- _this.framework.on('click', function() {
- Fx.click(_this.graphDiv, { target: true });
- });
+ _this.framework.on('click', function () {
+ Fx.click(_this.graphDiv, { target: true })
+ })
- topojsonNameNew = topojsonUtils.getTopojsonName(geoLayout);
+ topojsonNameNew = topojsonUtils.getTopojsonName(geoLayout)
- if(_this.topojson === null || topojsonNameNew !== _this.topojsonName) {
- _this.topojsonName = topojsonNameNew;
+ if (_this.topojson === null || topojsonNameNew !== _this.topojsonName) {
+ _this.topojsonName = topojsonNameNew
- if(PlotlyGeoAssets.topojson[_this.topojsonName] !== undefined) {
- _this.topojson = PlotlyGeoAssets.topojson[_this.topojsonName];
- _this.onceTopojsonIsLoaded(geoCalcData, geoLayout);
- }
- else {
- topojsonPath = topojsonUtils.getTopojsonPath(
+ if (PlotlyGeoAssets.topojson[_this.topojsonName] !== undefined) {
+ _this.topojson = PlotlyGeoAssets.topojson[_this.topojsonName]
+ _this.onceTopojsonIsLoaded(geoCalcData, geoLayout)
+ } else {
+ topojsonPath = topojsonUtils.getTopojsonPath(
_this.topojsonURL,
_this.topojsonName
- );
-
- promises.push(new Promise(function(resolve, reject) {
- d3.json(topojsonPath, function(error, topojson) {
- if(error) {
- if(error.status === 404) {
- reject(new Error([
- 'plotly.js could not find topojson file at',
- topojsonPath, '.',
- 'Make sure the *topojsonURL* plot config option',
- 'is set properly.'
- ].join(' ')));
- }
- else {
- reject(new Error([
- 'unexpected error while fetching topojson file at',
- topojsonPath
- ].join(' ')));
- }
- return;
- }
-
- _this.topojson = topojson;
- PlotlyGeoAssets.topojson[_this.topojsonName] = topojson;
-
- _this.onceTopojsonIsLoaded(geoCalcData, geoLayout);
- resolve();
- });
- }));
- }
+ )
+
+ promises.push(new Promise(function (resolve, reject) {
+ d3.json(topojsonPath, function (error, topojson) {
+ if (error) {
+ if (error.status === 404) {
+ reject(new Error([
+ 'plotly.js could not find topojson file at',
+ topojsonPath, '.',
+ 'Make sure the *topojsonURL* plot config option',
+ 'is set properly.'
+ ].join(' ')))
+ } else {
+ reject(new Error([
+ 'unexpected error while fetching topojson file at',
+ topojsonPath
+ ].join(' ')))
+ }
+ return
+ }
+
+ _this.topojson = topojson
+ PlotlyGeoAssets.topojson[_this.topojsonName] = topojson
+
+ _this.onceTopojsonIsLoaded(geoCalcData, geoLayout)
+ resolve()
+ })
+ }))
}
- else _this.onceTopojsonIsLoaded(geoCalcData, geoLayout);
+ } else _this.onceTopojsonIsLoaded(geoCalcData, geoLayout)
// TODO handle topojson-is-loading case
// to avoid making multiple request while streaming
-};
+}
-proto.onceTopojsonIsLoaded = function(geoCalcData, geoLayout) {
- this.drawLayout(geoLayout);
+proto.onceTopojsonIsLoaded = function (geoCalcData, geoLayout) {
+ this.drawLayout(geoLayout)
- Plots.generalUpdatePerTraceModule(this, geoCalcData, geoLayout);
+ Plots.generalUpdatePerTraceModule(this, geoCalcData, geoLayout)
- this.render();
-};
+ this.render()
+}
-proto.updateFx = function(hovermode) {
- this.showHover = (hovermode !== false);
+proto.updateFx = function (hovermode) {
+ this.showHover = (hovermode !== false)
// TODO should more strict, any layout.hovermode other
// then false will make all geo subplot display hover text.
// Instead each geo should have its own geo.hovermode
// to control hover visibility independently of other subplots.
-};
+}
-proto.makeProjection = function(geoLayout) {
- var projLayout = geoLayout.projection,
- projType = projLayout.type,
- isNew = this.projection === null || projType !== this.projectionType,
- projection;
+proto.makeProjection = function (geoLayout) {
+ var projLayout = geoLayout.projection,
+ projType = projLayout.type,
+ isNew = this.projection === null || projType !== this.projectionType,
+ projection
- if(isNew) {
- this.projectionType = projType;
- projection = this.projection = d3.geo[constants.projNames[projType]]();
- }
- else projection = this.projection;
+ if (isNew) {
+ this.projectionType = projType
+ projection = this.projection = d3.geo[constants.projNames[projType]]()
+ } else projection = this.projection
- projection
+ projection
.translate(projLayout._translate0)
- .precision(constants.precision);
+ .precision(constants.precision)
- if(!geoLayout._isAlbersUsa) {
- projection
+ if (!geoLayout._isAlbersUsa) {
+ projection
.rotate(projLayout._rotate)
- .center(projLayout._center);
- }
+ .center(projLayout._center)
+ }
- if(geoLayout._clipAngle) {
- this.clipAngle = geoLayout._clipAngle; // needed in proto.render
- projection
- .clipAngle(geoLayout._clipAngle - constants.clipPad);
- }
- else this.clipAngle = null; // for graph edits
+ if (geoLayout._clipAngle) {
+ this.clipAngle = geoLayout._clipAngle // needed in proto.render
+ projection
+ .clipAngle(geoLayout._clipAngle - constants.clipPad)
+ } else this.clipAngle = null // for graph edits
- if(projLayout.parallels) {
- projection
- .parallels(projLayout.parallels);
- }
+ if (projLayout.parallels) {
+ projection
+ .parallels(projLayout.parallels)
+ }
- if(isNew) this.setScale(projection);
+ if (isNew) this.setScale(projection)
- projection
+ projection
.translate(projLayout._translate)
- .scale(projLayout._scale);
-};
+ .scale(projLayout._scale)
+}
-proto.makePath = function() {
- this.path = d3.geo.path().projection(this.projection);
-};
+proto.makePath = function () {
+ this.path = d3.geo.path().projection(this.projection)
+}
/*
*
@@ -238,271 +231,267 @@ proto.makePath = function() {
*