Skip to content

Commit 8e2a321

Browse files
committed
template-safe GUI editing of array objects
1 parent e306d1c commit 8e2a321

File tree

7 files changed

+220
-116
lines changed

7 files changed

+220
-116
lines changed

src/components/annotations/click.js

+14-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88

99
'use strict';
1010

11+
var Lib = require('../../lib');
1112
var Registry = require('../../registry');
13+
var arrayEditor = require('../../plot_api/plot_template').arrayEditor;
1214

1315
module.exports = {
1416
hasClickToShow: hasClickToShow,
@@ -41,20 +43,25 @@ function hasClickToShow(gd, hoverData) {
4143
* returns: Promise that the update is complete
4244
*/
4345
function onClick(gd, hoverData) {
44-
var toggleSets = getToggleSets(gd, hoverData),
45-
onSet = toggleSets.on,
46-
offSet = toggleSets.off.concat(toggleSets.explicitOff),
47-
update = {},
48-
i;
46+
var toggleSets = getToggleSets(gd, hoverData);
47+
var onSet = toggleSets.on;
48+
var offSet = toggleSets.off.concat(toggleSets.explicitOff);
49+
var update = {};
50+
var annotationsOut = gd._fullLayout.annotations;
51+
var i, editHelpers;
4952

5053
if(!(onSet.length || offSet.length)) return;
5154

5255
for(i = 0; i < onSet.length; i++) {
53-
update['annotations[' + onSet[i] + '].visible'] = true;
56+
editHelpers = arrayEditor(gd.layout, 'annotations', annotationsOut[onSet[i]]);
57+
editHelpers.modifyItem('visible', true);
58+
Lib.extendFlat(update, editHelpers.getUpdateObj());
5459
}
5560

5661
for(i = 0; i < offSet.length; i++) {
57-
update['annotations[' + offSet[i] + '].visible'] = false;
62+
editHelpers = arrayEditor(gd.layout, 'annotations', annotationsOut[offSet[i]]);
63+
editHelpers.modifyItem('visible', false);
64+
Lib.extendFlat(update, editHelpers.getUpdateObj());
5865
}
5966

6067
return Registry.call('update', gd, {}, update);

src/components/annotations/draw.js

+39-36
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ var Fx = require('../fx');
2020
var svgTextUtils = require('../../lib/svg_text_utils');
2121
var setCursor = require('../../lib/setcursor');
2222
var dragElement = require('../dragelement');
23+
var arrayEditor = require('../../plot_api/plot_template').arrayEditor;
24+
2325
var drawArrowHead = require('./draw_arrow_head');
2426

2527
// Annotations are stored in gd.layout.annotations, an array of objects
@@ -84,17 +86,21 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
8486
var gs = gd._fullLayout._size;
8587
var edits = gd._context.edits;
8688

87-
var className;
88-
var annbase;
89+
var className, containerStr;
8990

9091
if(subplotId) {
9192
className = 'annotation-' + subplotId;
92-
annbase = subplotId + '.annotations[' + index + ']';
93+
containerStr = subplotId + '.annotations';
9394
} else {
9495
className = 'annotation';
95-
annbase = 'annotations[' + index + ']';
96+
containerStr = 'annotations';
9697
}
9798

99+
var editHelpers = arrayEditor(gd.layout, containerStr, options);
100+
var modifyBase = editHelpers.modifyBase;
101+
var modifyItem = editHelpers.modifyItem;
102+
var getUpdateObj = editHelpers.getUpdateObj;
103+
98104
// remove the existing annotation if there is one
99105
fullLayout._infolayer
100106
.selectAll('.' + className + '[data-index="' + index + '"]')
@@ -542,9 +548,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
542548
.call(Color.stroke, 'rgba(0,0,0,0)')
543549
.call(Color.fill, 'rgba(0,0,0,0)');
544550

545-
var update,
546-
annx0,
547-
anny0;
551+
var annx0, anny0;
548552

549553
// dragger for the arrow & head: translates the whole thing
550554
// (head/tail/text) all together
@@ -556,12 +560,11 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
556560

557561
annx0 = pos.x;
558562
anny0 = pos.y;
559-
update = {};
560563
if(xa && xa.autorange) {
561-
update[xa._name + '.autorange'] = true;
564+
modifyBase(xa._name + '.autorange', true);
562565
}
563566
if(ya && ya.autorange) {
564-
update[ya._name + '.autorange'] = true;
567+
modifyBase(ya._name + '.autorange', true);
565568
}
566569
},
567570
moveFn: function(dx, dy) {
@@ -570,19 +573,19 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
570573
ycenter = annxy0[1] + dy;
571574
annTextGroupInner.call(Drawing.setTranslate, xcenter, ycenter);
572575

573-
update[annbase + '.x'] = xa ?
576+
modifyItem('x', xa ?
574577
xa.p2r(xa.r2p(options.x) + dx) :
575-
(options.x + (dx / gs.w));
576-
update[annbase + '.y'] = ya ?
578+
(options.x + (dx / gs.w)));
579+
modifyItem('y', ya ?
577580
ya.p2r(ya.r2p(options.y) + dy) :
578-
(options.y - (dy / gs.h));
581+
(options.y - (dy / gs.h)));
579582

580583
if(options.axref === options.xref) {
581-
update[annbase + '.ax'] = xa.p2r(xa.r2p(options.ax) + dx);
584+
modifyItem('ax', xa.p2r(xa.r2p(options.ax) + dx));
582585
}
583586

584587
if(options.ayref === options.yref) {
585-
update[annbase + '.ay'] = ya.p2r(ya.r2p(options.ay) + dy);
588+
modifyItem('ay', ya.p2r(ya.r2p(options.ay) + dy));
586589
}
587590

588591
arrowGroup.attr('transform', 'translate(' + dx + ',' + dy + ')');
@@ -592,7 +595,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
592595
});
593596
},
594597
doneFn: function() {
595-
Registry.call('relayout', gd, update);
598+
Registry.call('relayout', gd, getUpdateObj());
596599
var notesBox = document.querySelector('.js-notes-box-panel');
597600
if(notesBox) notesBox.redraw(notesBox.selectedObj);
598601
}
@@ -604,8 +607,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
604607

605608
// user dragging the annotation (text, not arrow)
606609
if(editTextPosition) {
607-
var update,
608-
baseTextTransform;
610+
var baseTextTransform;
609611

610612
// dragger for the textbox: if there's an arrow, just drag the
611613
// textbox and tail, leave the head untouched
@@ -614,52 +616,54 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
614616
gd: gd,
615617
prepFn: function() {
616618
baseTextTransform = annTextGroup.attr('transform');
617-
update = {};
618619
},
619620
moveFn: function(dx, dy) {
620621
var csr = 'pointer';
621622
if(options.showarrow) {
622623
if(options.axref === options.xref) {
623-
update[annbase + '.ax'] = xa.p2r(xa.r2p(options.ax) + dx);
624+
modifyItem('ax', xa.p2r(xa.r2p(options.ax) + dx));
624625
} else {
625-
update[annbase + '.ax'] = options.ax + dx;
626+
modifyItem('ax', options.ax + dx);
626627
}
627628

628629
if(options.ayref === options.yref) {
629-
update[annbase + '.ay'] = ya.p2r(ya.r2p(options.ay) + dy);
630+
modifyItem('ay', ya.p2r(ya.r2p(options.ay) + dy));
630631
} else {
631-
update[annbase + '.ay'] = options.ay + dy;
632+
modifyItem('ay', options.ay + dy);
632633
}
633634

634635
drawArrow(dx, dy);
635636
}
636637
else if(!subplotId) {
638+
var xUpdate, yUpdate;
637639
if(xa) {
638-
update[annbase + '.x'] = xa.p2r(xa.r2p(options.x) + dx);
640+
xUpdate = xa.p2r(xa.r2p(options.x) + dx);
639641

640642
} else {
641643
var widthFraction = options._xsize / gs.w,
642644
xLeft = options.x + (options._xshift - options.xshift) / gs.w -
643645
widthFraction / 2;
644646

645-
update[annbase + '.x'] = dragElement.align(xLeft + dx / gs.w,
647+
xUpdate = dragElement.align(xLeft + dx / gs.w,
646648
widthFraction, 0, 1, options.xanchor);
647649
}
648650

649651
if(ya) {
650-
update[annbase + '.y'] = ya.p2r(ya.r2p(options.y) + dy);
652+
yUpdate = ya.p2r(ya.r2p(options.y) + dy);
651653
} else {
652654
var heightFraction = options._ysize / gs.h,
653655
yBottom = options.y - (options._yshift + options.yshift) / gs.h -
654656
heightFraction / 2;
655657

656-
update[annbase + '.y'] = dragElement.align(yBottom - dy / gs.h,
658+
yUpdate = dragElement.align(yBottom - dy / gs.h,
657659
heightFraction, 0, 1, options.yanchor);
658660
}
661+
modifyItem('x', xUpdate);
662+
modifyItem('y', yUpdate);
659663
if(!xa || !ya) {
660664
csr = dragElement.getCursor(
661-
xa ? 0.5 : update[annbase + '.x'],
662-
ya ? 0.5 : update[annbase + '.y'],
665+
xa ? 0.5 : xUpdate,
666+
ya ? 0.5 : yUpdate,
663667
options.xanchor, options.yanchor
664668
);
665669
}
@@ -674,7 +678,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
674678
},
675679
doneFn: function() {
676680
setCursor(annTextGroupInner);
677-
Registry.call('relayout', gd, update);
681+
Registry.call('relayout', gd, getUpdateObj());
678682
var notesBox = document.querySelector('.js-notes-box-panel');
679683
if(notesBox) notesBox.redraw(notesBox.selectedObj);
680684
}
@@ -689,17 +693,16 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
689693
options.text = _text;
690694
this.call(textLayout);
691695

692-
var update = {};
693-
update[annbase + '.text'] = options.text;
696+
modifyItem('text', _text);
694697

695698
if(xa && xa.autorange) {
696-
update[xa._name + '.autorange'] = true;
699+
modifyBase(xa._name + '.autorange', true);
697700
}
698701
if(ya && ya.autorange) {
699-
update[ya._name + '.autorange'] = true;
702+
modifyBase(ya._name + '.autorange', true);
700703
}
701704

702-
Registry.call('relayout', gd, update);
705+
Registry.call('relayout', gd, getUpdateObj());
703706
});
704707
}
705708
else annText.call(textLayout);

0 commit comments

Comments
 (0)