Skip to content

Commit be5ae0f

Browse files
committed
Merge branch 'master' into mapbox_react_updates
2 parents 7e355d7 + c75c3ec commit be5ae0f

Some content is hidden

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

60 files changed

+1787
-85
lines changed

lib/locales/ko.js

+54-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/**
1+
/**
22
* Copyright 2012-2019, Plotly, Inc.
33
* All rights reserved.
44
*
@@ -11,7 +11,59 @@
1111
module.exports = {
1212
moduleType: 'locale',
1313
name: 'ko',
14-
dictionary: {},
14+
dictionary: {
15+
'Autoscale': '자동 크기지정',
16+
'Box Select': '박스 선택',
17+
'Click to enter Colorscale title': 'Colorscale 제목을 지정하려면 클릭하세요',
18+
'Click to enter Component A title': 'A데이터의 제목을 지정하려면 클릭하세요',
19+
'Click to enter Component B title': 'B데이터의 제목을 지정하려면 클릭하세요',
20+
'Click to enter Component C title': 'C데이터의 제목을 지정하려면 클릭하세요',
21+
'Click to enter Plot title': '차트 제목을 지정하려면 클릭하세요',
22+
'Click to enter X axis title': 'X축 제목을 지정하려면 클릭하세요',
23+
'Click to enter Y axis title': 'Y축 제목을 지정하려면 클릭하세요',
24+
'Click to enter radial axis title': '원형 축 제목을 지정하려면 클릭하세요',
25+
'Compare data on hover': '마우스를 올리면 데이터와 비교합니다',
26+
'Double-click on legend to isolate one trace': '범례를 더블 클릭하여 하나의 트레이스를 분리합니다',
27+
'Double-click to zoom back out': '더블 클릭하여 줌을 해제합니다',
28+
'Download plot as a png': '.png 이미지 파일로 차트를 다운로드 합니다',
29+
'Download plot': '차트를 다운로드 합니다',
30+
'Edit in Chart Studio': 'Chart Studio를 수정합니다',
31+
'IE only supports svg. Changing format to svg.': 'IE는 svg만을 지원합니다. 포맷을 svg로 변경하세요',
32+
'Lasso Select': '올가미 선택',
33+
'Orbital rotation': '궤도 수정',
34+
'Pan': '이동',
35+
'Produced with Plotly': 'Plotly 제공',
36+
'Reset': '초기화',
37+
'Reset axes': '축 초기화',
38+
'Reset camera to default': 'camera를 기본값으로 초기화',
39+
'Reset camera to last save': 'camera를 마지막으로 저장한 값으로 초기화',
40+
'Reset view': 'view 초기화',
41+
'Reset views': 'views 초기화',
42+
'Show closest data on hover': '마우스를 올리면 근접한 데이터를 보이기',
43+
'Snapshot succeeded': 'Snapshot 성공',
44+
'Sorry, there was a problem downloading your snapshot!': '죄송합니다, snapshot을 다운로드 중 문제가 발생했습니다!',
45+
'Taking snapshot - this may take a few seconds': 'snapshot 찍기 - 수 초가 걸릴 수 있습니다',
46+
'Toggle Spike Lines': '스위치로 Lines을 고정합니다',
47+
'Toggle show closest data on hover': '스위치로 마우스를 올렸을 때 가장 가까운 데이터를 보여줍니다',
48+
'Turntable rotation': 'Turntable 회전',
49+
'Zoom': '확대(줌)',
50+
'Zoom in': '확대(줌 인)',
51+
'Zoom out': '축소(줌 아웃)',
52+
'close': '닫기',
53+
'high': '높음',
54+
'low': '낮음',
55+
'max': '최댓값',
56+
'mean ± σ': '평균 ± σ',
57+
'mean': '평균',
58+
'median': '중간 값',
59+
'min': '최솟값',
60+
'new text': '새로운 텍스트',
61+
'open': '열기',
62+
'q1': 'q1',
63+
'q3': 'q3',
64+
'source': '소스',
65+
'target': '타겟',
66+
},
1567
format: {
1668
days: ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'],
1769
shortDays: ['일', '월', '화', '수', '목', '금', '토'],

src/components/legend/attributes.js

+33
Original file line numberDiff line numberDiff line change
@@ -193,5 +193,38 @@ module.exports = {
193193
'Sets the vertical alignment of the symbols with respect to their associated text.',
194194
].join(' ')
195195
},
196+
title: {
197+
text: {
198+
valType: 'string',
199+
dflt: '',
200+
role: 'info',
201+
editType: 'legend',
202+
description: [
203+
'Sets the title of the legend.'
204+
].join(' ')
205+
},
206+
font: fontAttrs({
207+
editType: 'legend',
208+
description: [
209+
'Sets this legend\'s title font.'
210+
].join(' '),
211+
}),
212+
side: {
213+
valType: 'enumerated',
214+
values: ['top', 'left', 'top left'],
215+
role: 'style',
216+
editType: 'legend',
217+
description: [
218+
'Determines the location of legend\'s title',
219+
'with respect to the legend items.',
220+
'Defaulted to *top* with `orientation` is *h*.',
221+
'Defaulted to *left* with `orientation` is *v*.',
222+
'The *top left* options could be used to expand',
223+
'legend area in both x and y sides.'
224+
].join(' ')
225+
},
226+
editType: 'legend',
227+
},
228+
196229
editType: 'legend'
197230
};

src/components/legend/constants.js

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ module.exports = {
1515
scrollBarMargin: 4,
1616
scrollBarEnterAttrs: {rx: 20, ry: 3, width: 0, height: 0},
1717

18+
// number of px between legend title and (left) side of legend (always in x direction and from inner border)
19+
titlePad: 2,
1820
// number of px between legend symbol and legend text (always in x direction)
1921
textGap: 40,
2022
// number of px between each legend item (x and/or y direction)

src/components/legend/defaults.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,14 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
3333
// *would* be shown by default, toward the two traces you need to
3434
// ensure the legend is shown by default, because this can still help
3535
// disambiguate.
36-
if(trace.showlegend || trace._dfltShowLegend) {
36+
if(trace.showlegend || (
37+
trace._dfltShowLegend && !(
38+
trace._module &&
39+
trace._module.attributes &&
40+
trace._module.attributes.showlegend &&
41+
trace._module.attributes.showlegend.dflt === false
42+
)
43+
)) {
3744
legendTraceCount++;
3845
if(trace.showlegend) {
3946
legendReallyHasATrace = true;
@@ -116,4 +123,10 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
116123
coerce('yanchor', defaultYAnchor);
117124
coerce('valign');
118125
Lib.noneOrAll(containerIn, containerOut, ['x', 'y']);
126+
127+
var titleText = coerce('title.text');
128+
if(titleText) {
129+
coerce('title.side', orientation === 'h' ? 'left' : 'top');
130+
Lib.coerceFont(coerce, 'title.font', layoutOut.font);
131+
}
119132
};

src/components/legend/draw.js

+95-28
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,19 @@ module.exports = function draw(gd) {
6565

6666
var scrollBox = Lib.ensureSingle(legend, 'g', 'scrollbox');
6767

68+
var title = opts.title;
69+
opts._titleWidth = 0;
70+
opts._titleHeight = 0;
71+
if(title.text) {
72+
var titleEl = Lib.ensureSingle(scrollBox, 'text', 'legendtitletext');
73+
titleEl.attr('text-anchor', 'start')
74+
.classed('user-select-none', true)
75+
.call(Drawing.font, title.font)
76+
.text(title.text);
77+
78+
textLayout(titleEl, scrollBox, gd); // handle mathjax or multi-line text and compute title height
79+
}
80+
6881
var scrollBar = Lib.ensureSingle(legend, 'rect', 'scrollbar', function(s) {
6982
s.attr(constants.scrollBarEnterAttrs)
7083
.call(Color.fill, constants.scrollBarColor);
@@ -121,7 +134,7 @@ module.exports = function draw(gd) {
121134
}
122135

123136
// Set size and position of all the elements that make up a legend:
124-
// legend, background and border, scroll box and scroll bar
137+
// legend, background and border, scroll box and scroll bar as well as title
125138
Drawing.setTranslate(legend, lx, ly);
126139

127140
// to be safe, remove previous listeners
@@ -370,23 +383,17 @@ function drawTexts(g, gd) {
370383

371384
textEl.attr('text-anchor', 'start')
372385
.classed('user-select-none', true)
373-
.call(Drawing.font, fullLayout.legend.font)
386+
.call(Drawing.font, opts.font)
374387
.text(isEditable ? ensureLength(name, maxNameLength) : name);
375388

376389
svgTextUtils.positionText(textEl, constants.textGap, 0);
377390

378-
function textLayout(s) {
379-
svgTextUtils.convertToTspans(s, gd, function() {
380-
computeTextDimensions(g, gd);
381-
});
382-
}
383-
384391
if(isEditable) {
385392
textEl.call(svgTextUtils.makeEditable, {gd: gd, text: name})
386-
.call(textLayout)
393+
.call(textLayout, g, gd)
387394
.on('edit', function(newName) {
388395
this.text(ensureLength(newName, maxNameLength))
389-
.call(textLayout);
396+
.call(textLayout, g, gd);
390397

391398
var fullInput = legendItem.trace._fullInput || {};
392399
var update = {};
@@ -407,7 +414,7 @@ function drawTexts(g, gd) {
407414
return Registry.call('_guiRestyle', gd, update, traceIndex);
408415
});
409416
} else {
410-
textLayout(textEl);
417+
textLayout(textEl, g, gd);
411418
}
412419
}
413420

@@ -460,18 +467,24 @@ function setupTraceToggle(g, gd) {
460467
});
461468
}
462469

470+
function textLayout(s, g, gd) {
471+
svgTextUtils.convertToTspans(s, gd, function() {
472+
computeTextDimensions(g, gd);
473+
});
474+
}
475+
463476
function computeTextDimensions(g, gd) {
464477
var legendItem = g.data()[0][0];
465-
466-
if(!legendItem.trace.showlegend) {
478+
if(legendItem && !legendItem.trace.showlegend) {
467479
g.remove();
468480
return;
469481
}
470482

471483
var mathjaxGroup = g.select('g[class*=math-group]');
472484
var mathjaxNode = mathjaxGroup.node();
485+
var bw = gd._fullLayout.legend.borderwidth;
473486
var opts = gd._fullLayout.legend;
474-
var lineHeight = opts.font.size * LINE_SPACING;
487+
var lineHeight = (legendItem ? opts : opts.title).font.size * LINE_SPACING;
475488
var height, width;
476489

477490
if(mathjaxNode) {
@@ -480,24 +493,56 @@ function computeTextDimensions(g, gd) {
480493
height = mathjaxBB.height;
481494
width = mathjaxBB.width;
482495

483-
Drawing.setTranslate(mathjaxGroup, 0, (height / 4));
496+
if(legendItem) {
497+
Drawing.setTranslate(mathjaxGroup, 0, height * 0.25);
498+
} else { // case of title
499+
Drawing.setTranslate(mathjaxGroup, bw, height * 0.75 + bw);
500+
}
484501
} else {
485-
var text = g.select('.legendtext');
486-
var textLines = svgTextUtils.lineCount(text);
487-
var textNode = text.node();
502+
var textEl = g.select(legendItem ?
503+
'.legendtext' : '.legendtitletext'
504+
);
505+
var textLines = svgTextUtils.lineCount(textEl);
506+
var textNode = textEl.node();
488507

489508
height = lineHeight * textLines;
490509
width = textNode ? Drawing.bBox(textNode).width : 0;
491510

492511
// approximation to height offset to center the font
493512
// to avoid getBoundingClientRect
494-
var textY = lineHeight * (0.3 + (1 - textLines) / 2);
495-
svgTextUtils.positionText(text, constants.textGap, textY);
513+
var textY = lineHeight * ((textLines - 1) / 2 - 0.3);
514+
if(legendItem) {
515+
svgTextUtils.positionText(textEl, constants.textGap, -textY);
516+
} else { // case of title
517+
svgTextUtils.positionText(textEl, constants.titlePad + bw, lineHeight + bw);
518+
}
519+
}
520+
521+
if(legendItem) {
522+
legendItem.lineHeight = lineHeight;
523+
legendItem.height = Math.max(height, 16) + 3;
524+
legendItem.width = width;
525+
} else { // case of title
526+
opts._titleWidth = width;
527+
opts._titleHeight = height;
528+
}
529+
}
530+
531+
function getTitleSize(opts) {
532+
var w = 0;
533+
var h = 0;
534+
535+
var side = opts.title.side;
536+
if(side) {
537+
if(side.indexOf('left') !== -1) {
538+
w = opts._titleWidth;
539+
}
540+
if(side.indexOf('top') !== -1) {
541+
h = opts._titleHeight;
542+
}
496543
}
497544

498-
legendItem.lineHeight = lineHeight;
499-
legendItem.height = Math.max(height, 16) + 3;
500-
legendItem.width = width;
545+
return [w, h];
501546
}
502547

503548
/*
@@ -514,6 +559,7 @@ function computeLegendDimensions(gd, groups, traces) {
514559
var fullLayout = gd._fullLayout;
515560
var opts = fullLayout.legend;
516561
var gs = fullLayout._size;
562+
517563
var isVertical = helpers.isVertical(opts);
518564
var isGrouped = helpers.isGrouped(opts);
519565

@@ -537,11 +583,15 @@ function computeLegendDimensions(gd, groups, traces) {
537583
var toggleRectWidth = 0;
538584
opts._width = 0;
539585
opts._height = 0;
586+
var titleSize = getTitleSize(opts);
540587

541588
if(isVertical) {
542589
traces.each(function(d) {
543590
var h = d[0].height;
544-
Drawing.setTranslate(this, bw, itemGap + bw + opts._height + h / 2);
591+
Drawing.setTranslate(this,
592+
bw + titleSize[0],
593+
bw + titleSize[1] + opts._height + h / 2 + itemGap
594+
);
545595
opts._height += h;
546596
opts._width = Math.max(opts._width, d[0].width);
547597
});
@@ -591,7 +641,10 @@ function computeLegendDimensions(gd, groups, traces) {
591641
var offsetY = 0;
592642
d3.select(this).selectAll('g.traces').each(function(d) {
593643
var h = d[0].height;
594-
Drawing.setTranslate(this, 0, itemGap + bw + h / 2 + offsetY);
644+
Drawing.setTranslate(this,
645+
titleSize[0],
646+
titleSize[1] + bw + itemGap + h / 2 + offsetY
647+
);
595648
offsetY += h;
596649
maxWidthInGroup = Math.max(maxWidthInGroup, textGap + d[0].width);
597650
});
@@ -634,7 +687,10 @@ function computeLegendDimensions(gd, groups, traces) {
634687
maxItemHeightInRow = 0;
635688
}
636689

637-
Drawing.setTranslate(this, bw + offsetX, itemGap + bw + h / 2 + offsetY);
690+
Drawing.setTranslate(this,
691+
titleSize[0] + bw + offsetX,
692+
titleSize[1] + bw + offsetY + h / 2 + itemGap
693+
);
638694

639695
rowWidth = offsetX + w + itemGap;
640696
offsetX += next;
@@ -651,8 +707,19 @@ function computeLegendDimensions(gd, groups, traces) {
651707
}
652708
}
653709

654-
opts._width = Math.ceil(opts._width);
655-
opts._height = Math.ceil(opts._height);
710+
opts._width = Math.ceil(
711+
Math.max(
712+
opts._width + titleSize[0],
713+
opts._titleWidth + 2 * (bw + constants.titlePad)
714+
)
715+
);
716+
717+
opts._height = Math.ceil(
718+
Math.max(
719+
opts._height + titleSize[1],
720+
opts._titleHeight + 2 * (bw + constants.itemGap)
721+
)
722+
);
656723

657724
opts._effHeight = Math.min(opts._height, opts._maxHeight);
658725

src/components/legend/handle_click.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,12 @@ module.exports = function handleClick(g, gd, numClicks) {
165165
} else if(mode === 'toggleothers') {
166166
// Compute the clicked index. expandedIndex does what we want for expanded traces
167167
// but also culls hidden traces. That means we have some work to do.
168-
var isClicked, isInGroup, otherState;
168+
var isClicked, isInGroup, notInLegend, otherState;
169169
var isIsolated = true;
170170
for(i = 0; i < fullData.length; i++) {
171171
isClicked = fullData[i] === fullTrace;
172-
if(isClicked) continue;
172+
notInLegend = fullData[i].showlegend !== true;
173+
if(isClicked || notInLegend) continue;
173174

174175
isInGroup = (hasLegendgroup && fullData[i].legendgroup === legendgroup);
175176

@@ -194,8 +195,10 @@ module.exports = function handleClick(g, gd, numClicks) {
194195
case true:
195196
otherState = isIsolated ? true : 'legendonly';
196197
isClicked = fullData[i] === fullTrace;
198+
// N.B. consider traces that have a set legendgroup as toggleable
199+
notInLegend = (fullData[i].showlegend !== true && !fullData[i].legendgroup);
197200
isInGroup = isClicked || (hasLegendgroup && fullData[i].legendgroup === legendgroup);
198-
setVisibility(fullData[i], isInGroup ? true : otherState);
201+
setVisibility(fullData[i], (isInGroup || notInLegend) ? true : otherState);
199202
break;
200203
}
201204
}

0 commit comments

Comments
 (0)