Skip to content

Commit 48da987

Browse files
Merge branch 'master' into label_automargin
2 parents c1f7df4 + 113b361 commit 48da987

File tree

117 files changed

+1654
-619
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

117 files changed

+1654
-619
lines changed

.eslintrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"Int16Array": true,
1818
"Int32Array": true,
1919
"ArrayBuffer": true,
20+
"DataView": true,
2021
"SVGElement": false
2122
},
2223
"rules": {

src/components/colorscale/has_colorscale.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,20 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
109
'use strict';
1110

1211
var isNumeric = require('fast-isnumeric');
13-
1412
var Lib = require('../../lib');
15-
1613
var isValidScale = require('./is_valid_scale');
1714

18-
1915
module.exports = function hasColorscale(trace, containerStr) {
2016
var container = containerStr ?
21-
Lib.nestedProperty(trace, containerStr).get() || {} :
22-
trace,
23-
color = container.color,
24-
isArrayWithOneNumber = false;
17+
Lib.nestedProperty(trace, containerStr).get() || {} :
18+
trace;
19+
var color = container.color;
2520

26-
if(Array.isArray(color)) {
21+
var isArrayWithOneNumber = false;
22+
if(Lib.isArrayOrTypedArray(color)) {
2723
for(var i = 0; i < color.length; i++) {
2824
if(isNumeric(color[i])) {
2925
isArrayWithOneNumber = true;

src/components/dragelement/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ dragElement.init = function init(options) {
135135
startY = offset[1];
136136
initialTarget = e.target;
137137
initialEvent = e;
138-
rightClick = (e.buttons && e.buttons === 2) || e.ctrlKey;
138+
rightClick = e.buttons === 2 || e.ctrlKey;
139139

140140
newMouseDownTime = (new Date()).getTime();
141141
if(newMouseDownTime - gd._mouseDownTime < DBLCLICKDELAY) {

src/components/drawing/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,10 +316,10 @@ function singlePointStyle(d, sel, trace, markerScale, lineScale, marker, markerL
316316

317317
if('mlc' in d) lineColor = d.mlcc = lineScale(d.mlc);
318318
// weird case: array wasn't long enough to apply to every point
319-
else if(Array.isArray(markerLine.color)) lineColor = Color.defaultLine;
319+
else if(Lib.isArrayOrTypedArray(markerLine.color)) lineColor = Color.defaultLine;
320320
else lineColor = markerLine.color;
321321

322-
if(Array.isArray(marker.color)) {
322+
if(Lib.isArrayOrTypedArray(marker.color)) {
323323
fillColor = Color.defaultLine;
324324
perPointGradient = true;
325325
}
@@ -542,7 +542,7 @@ drawing.tryColorscale = function(marker, prefix) {
542542
scl = cont.colorscale,
543543
colorArray = cont.color;
544544

545-
if(scl && Array.isArray(colorArray)) {
545+
if(scl && Lib.isArrayOrTypedArray(colorArray)) {
546546
return Colorscale.makeColorScaleFunc(
547547
Colorscale.extractScale(scl, cont.cmin, cont.cmax)
548548
);

src/components/legend/constants.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
'use strict';
1010

1111
module.exports = {
12-
scrollBarWidth: 4,
13-
scrollBarHeight: 20,
12+
scrollBarWidth: 6,
13+
scrollBarMinHeight: 20,
1414
scrollBarColor: '#808BA4',
1515
scrollBarMargin: 4
1616
};

src/components/legend/draw.js

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ module.exports = function draw(gd) {
7878
'shape-rendering': 'crispEdges'
7979
});
8080

81-
bg.call(Color.stroke, opts.bordercolor);
82-
bg.call(Color.fill, opts.bgcolor);
83-
bg.style('stroke-width', opts.borderwidth + 'px');
81+
bg.call(Color.stroke, opts.bordercolor)
82+
.call(Color.fill, opts.bgcolor)
83+
.style('stroke-width', opts.borderwidth + 'px');
8484

8585
var scrollBox = legend.selectAll('g.scrollbox')
8686
.data([0]);
@@ -94,10 +94,10 @@ module.exports = function draw(gd) {
9494
scrollBar.enter().append('rect')
9595
.attr({
9696
'class': 'scrollbar',
97-
'rx': 20,
98-
'ry': 2,
99-
'width': 0,
100-
'height': 0
97+
rx: 20,
98+
ry: 3,
99+
width: 0,
100+
height: 0
101101
})
102102
.call(Color.fill, '#808BA4');
103103

@@ -207,12 +207,9 @@ module.exports = function draw(gd) {
207207
// legend, background and border, scroll box and scroll bar
208208
Drawing.setTranslate(legend, lx, ly);
209209

210-
var scrollBarYMax = legendHeight -
211-
constants.scrollBarHeight -
212-
2 * constants.scrollBarMargin,
213-
scrollBoxYMax = opts._height - legendHeight,
214-
scrollBarY,
215-
scrollBoxY;
210+
// to be safe, remove previous listeners
211+
scrollBar.on('.drag', null);
212+
legend.on('wheel', null);
216213

217214
if(opts._height <= legendHeight || gd._context.staticPlot) {
218215
// if scrollbar should not be shown.
@@ -232,11 +229,21 @@ module.exports = function draw(gd) {
232229
y: opts.borderwidth
233230
});
234231

235-
scrollBox.call(Drawing.setClipUrl, clipId);
232+
Drawing.setClipUrl(scrollBox, clipId);
233+
234+
Drawing.setRect(scrollBar, 0, 0, 0, 0);
235+
delete opts._scrollY;
236236
}
237237
else {
238-
scrollBarY = constants.scrollBarMargin,
239-
scrollBoxY = scrollBox.attr('data-scroll') || 0;
238+
var scrollBarHeight = Math.max(constants.scrollBarMinHeight,
239+
legendHeight * legendHeight / opts._height);
240+
var scrollBarYMax = legendHeight -
241+
scrollBarHeight -
242+
2 * constants.scrollBarMargin;
243+
var scrollBoxYMax = opts._height - legendHeight;
244+
var scrollRatio = scrollBarYMax / scrollBoxYMax;
245+
246+
var scrollBoxY = Math.min(opts._scrollY || 0, scrollBoxYMax);
240247

241248
// increase the background and clip-path width
242249
// by the scrollbar width and margin
@@ -257,60 +264,58 @@ module.exports = function draw(gd) {
257264
constants.scrollBarMargin,
258265
height: legendHeight - 2 * opts.borderwidth,
259266
x: opts.borderwidth,
260-
y: opts.borderwidth - scrollBoxY
267+
y: opts.borderwidth + scrollBoxY
261268
});
262269

263-
scrollBox.call(Drawing.setClipUrl, clipId);
270+
Drawing.setClipUrl(scrollBox, clipId);
264271

265-
if(firstRender) scrollHandler(scrollBarY, scrollBoxY);
272+
scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio);
266273

267-
legend.on('wheel', null); // to be safe, remove previous listeners
268274
legend.on('wheel', function() {
269275
scrollBoxY = Lib.constrain(
270-
scrollBox.attr('data-scroll') -
276+
opts._scrollY +
271277
d3.event.deltaY / scrollBarYMax * scrollBoxYMax,
272-
-scrollBoxYMax, 0);
273-
scrollBarY = constants.scrollBarMargin -
274-
scrollBoxY / scrollBoxYMax * scrollBarYMax;
275-
scrollHandler(scrollBarY, scrollBoxY);
276-
if(scrollBoxY !== 0 && scrollBoxY !== -scrollBoxYMax) {
278+
0, scrollBoxYMax);
279+
scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio);
280+
if(scrollBoxY !== 0 && scrollBoxY !== scrollBoxYMax) {
277281
d3.event.preventDefault();
278282
}
279283
});
280284

281-
// to be safe, remove previous listeners
282-
scrollBar.on('.drag', null);
283-
scrollBox.on('.drag', null);
285+
var eventY0, scrollBoxY0;
284286

285-
var drag = d3.behavior.drag().on('drag', function() {
286-
scrollBarY = Lib.constrain(
287-
d3.event.y - constants.scrollBarHeight / 2,
288-
constants.scrollBarMargin,
289-
constants.scrollBarMargin + scrollBarYMax);
290-
scrollBoxY = - (scrollBarY - constants.scrollBarMargin) /
291-
scrollBarYMax * scrollBoxYMax;
292-
scrollHandler(scrollBarY, scrollBoxY);
287+
var drag = d3.behavior.drag()
288+
.on('dragstart', function() {
289+
eventY0 = d3.event.sourceEvent.clientY;
290+
scrollBoxY0 = scrollBoxY;
291+
})
292+
.on('drag', function() {
293+
var e = d3.event.sourceEvent;
294+
if(e.buttons === 2 || e.ctrlKey) return;
295+
296+
scrollBoxY = Lib.constrain(
297+
(e.clientY - eventY0) / scrollRatio + scrollBoxY0,
298+
0, scrollBoxYMax);
299+
scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio);
293300
});
294301

295302
scrollBar.call(drag);
296-
scrollBox.call(drag);
297303
}
298304

299305

300-
function scrollHandler(scrollBarY, scrollBoxY) {
301-
scrollBox
302-
.attr('data-scroll', scrollBoxY)
303-
.call(Drawing.setTranslate, 0, scrollBoxY);
306+
function scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio) {
307+
opts._scrollY = gd._fullLayout.legend._scrollY = scrollBoxY;
308+
Drawing.setTranslate(scrollBox, 0, -scrollBoxY);
304309

305-
scrollBar.call(
306-
Drawing.setRect,
310+
Drawing.setRect(
311+
scrollBar,
307312
legendWidth,
308-
scrollBarY,
313+
constants.scrollBarMargin + scrollBoxY * scrollRatio,
309314
constants.scrollBarWidth,
310-
constants.scrollBarHeight
315+
scrollBarHeight
311316
);
312317
clipPath.select('rect').attr({
313-
y: opts.borderwidth - scrollBoxY
318+
y: opts.borderwidth + scrollBoxY
314319
});
315320
}
316321

@@ -434,7 +439,7 @@ function drawTexts(g, gd) {
434439
return Plotly.restyle(gd, update, traceIndex);
435440
});
436441
} else {
437-
text.call(textLayout);
442+
textLayout(text);
438443
}
439444
}
440445

@@ -664,7 +669,7 @@ function computeLegendDimensions(gd, groups, traces) {
664669
var legendItem = d[0],
665670
bg = d3.select(this).select('.legendtoggle');
666671

667-
bg.call(Drawing.setRect,
672+
Drawing.setRect(bg,
668673
0,
669674
-legendItem.height / 2,
670675
(gd._context.edits.legendText ? 0 : opts._width) + extraWidth,

src/lib/coerce.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,21 @@ var nestedProperty = require('./nested_property');
1919
var counterRegex = require('./regex').counter;
2020
var DESELECTDIM = require('../constants/interactions').DESELECTDIM;
2121
var wrap180 = require('./angles').wrap180;
22+
var isArrayOrTypedArray = require('./is_array').isArrayOrTypedArray;
2223

2324
exports.valObjectMeta = {
2425
data_array: {
2526
// You can use *dflt=[] to force said array to exist though.
2627
description: [
2728
'An {array} of data.',
28-
'The value MUST be an {array}, or we ignore it.'
29+
'The value MUST be an {array}, or we ignore it.',
30+
'Note that typed arrays (e.g. Float32Array) are supported.'
2931
].join(' '),
3032
requiredOpts: [],
3133
otherOpts: ['dflt'],
3234
coerceFunction: function(v, propOut, dflt) {
33-
if(Array.isArray(v)) propOut.set(v);
35+
// TODO maybe `v: {type: 'float32', vals: [/* ... */]}` also
36+
if(isArrayOrTypedArray(v)) propOut.set(v);
3437
else if(dflt !== undefined) propOut.set(dflt);
3538
}
3639
},
@@ -367,7 +370,7 @@ exports.coerce = function(containerIn, containerOut, attributes, attribute, dflt
367370
* individual form (eg. some array vals can be numbers, even if the
368371
* single values must be color strings)
369372
*/
370-
if(opts.arrayOk && Array.isArray(v)) {
373+
if(opts.arrayOk && isArrayOrTypedArray(v)) {
371374
propOut.set(v);
372375
return v;
373376
}
@@ -464,7 +467,7 @@ exports.coerceSelectionMarkerOpacity = function(traceOut, coerce) {
464467
//
465468
// Only give [un]selected.marker.opacity a default value if you don't
466469
// set any other [un]selected attributes.
467-
if(!Array.isArray(mo) && !traceOut.selected && !traceOut.unselected) {
470+
if(!isArrayOrTypedArray(mo) && !traceOut.selected && !traceOut.unselected) {
468471
smoDflt = mo;
469472
usmoDflt = DESELECTDIM * mo;
470473
}
@@ -476,7 +479,7 @@ exports.coerceSelectionMarkerOpacity = function(traceOut, coerce) {
476479
exports.validate = function(value, opts) {
477480
var valObjectDef = exports.valObjectMeta[opts.valType];
478481

479-
if(opts.arrayOk && Array.isArray(value)) return true;
482+
if(opts.arrayOk && isArrayOrTypedArray(value)) return true;
480483

481484
if(valObjectDef.validateFunction) {
482485
return valObjectDef.validateFunction(value, opts);

src/lib/extend.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ function _extend(inputs, isDeep, keepAllKeys, noArrayCopies) {
6565

6666
var input, key, src, copy, copyIsArray, clone, allPrimitives;
6767

68+
// TODO does this do the right thing for typed arrays?
69+
6870
if(length === 2 && isArray(target) && isArray(inputs[1]) && target.length === 0) {
6971

7072
allPrimitives = primitivesLoopSplice(inputs[1], target);

src/lib/index.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@ lib.nestedProperty = require('./nested_property');
2222
lib.keyedContainer = require('./keyed_container');
2323
lib.relativeAttr = require('./relative_attr');
2424
lib.isPlainObject = require('./is_plain_object');
25-
lib.isArray = require('./is_array');
2625
lib.mod = require('./mod');
2726
lib.toLogRange = require('./to_log_range');
2827
lib.relinkPrivateKeys = require('./relink_private');
2928
lib.ensureArray = require('./ensure_array');
3029

30+
var isArrayModule = require('./is_array');
31+
lib.isTypedArray = isArrayModule.isTypedArray;
32+
lib.isArrayOrTypedArray = isArrayModule.isArrayOrTypedArray;
33+
3134
var coerceModule = require('./coerce');
3235
lib.valObjectMeta = coerceModule.valObjectMeta;
3336
lib.coerce = coerceModule.coerce;
@@ -389,7 +392,7 @@ lib.noneOrAll = function(containerIn, containerOut, attrList) {
389392
* @param {string} cdAttr : calcdata key
390393
*/
391394
lib.mergeArray = function(traceAttr, cd, cdAttr) {
392-
if(Array.isArray(traceAttr)) {
395+
if(lib.isArrayOrTypedArray(traceAttr)) {
393396
var imax = Math.min(traceAttr.length, cd.length);
394397
for(var i = 0; i < imax; i++) cd[i][cdAttr] = traceAttr[i];
395398
}
@@ -408,7 +411,7 @@ lib.mergeArray = function(traceAttr, cd, cdAttr) {
408411
lib.fillArray = function(traceAttr, cd, cdAttr, fn) {
409412
fn = fn || lib.identity;
410413

411-
if(Array.isArray(traceAttr)) {
414+
if(lib.isArrayOrTypedArray(traceAttr)) {
412415
for(var i = 0; i < cd.length; i++) {
413416
cd[i][cdAttr] = fn(traceAttr[i]);
414417
}
@@ -429,8 +432,8 @@ lib.castOption = function(trace, ptNumber, astr, fn) {
429432

430433
var val = lib.nestedProperty(trace, astr).get();
431434

432-
if(Array.isArray(val)) {
433-
if(Array.isArray(ptNumber) && Array.isArray(val[ptNumber[0]])) {
435+
if(lib.isArrayOrTypedArray(val)) {
436+
if(Array.isArray(ptNumber) && lib.isArrayOrTypedArray(val[ptNumber[0]])) {
434437
return fn(val[ptNumber[0]][ptNumber[1]]);
435438
} else {
436439
return fn(val[ptNumber]);

src/lib/is_array.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,20 @@
88

99
'use strict';
1010

11-
/**
12-
* Return true for arrays, whether they're untyped or not.
13-
*/
11+
// IE9 fallbacks
1412

15-
// IE9 fallback
1613
var ab = (typeof ArrayBuffer === 'undefined' || !ArrayBuffer.isView) ?
1714
{isView: function() { return false; }} :
1815
ArrayBuffer;
1916

20-
module.exports = function isArray(a) {
21-
return Array.isArray(a) || ab.isView(a);
17+
var dv = (typeof DataView === 'undefined') ?
18+
function() {} :
19+
DataView;
20+
21+
exports.isTypedArray = function(a) {
22+
return ab.isView(a) && !(a instanceof dv);
23+
};
24+
25+
exports.isArrayOrTypedArray = function(a) {
26+
return Array.isArray(a) || exports.isTypedArray(a);
2227
};

0 commit comments

Comments
 (0)