@@ -39,43 +39,65 @@ module.exports = function handleClick(g, gd, numClicks) {
39
39
if ( legendItem . groupTitle && legendItem . noClick ) return ;
40
40
41
41
var fullData = gd . _fullData ;
42
+ var shapesWithLegend = ( fullLayout . shapes || [ ] ) . filter ( function ( d ) { return d . showlegend ; } ) ;
43
+ var allLegendItems = fullData . concat ( shapesWithLegend ) ;
44
+
42
45
var fullTrace = legendItem . trace ;
46
+ if ( fullTrace . _isShape ) {
47
+ fullTrace = fullTrace . _fullInput ;
48
+ }
49
+
43
50
var legendgroup = fullTrace . legendgroup ;
44
51
45
52
var i , j , kcont , key , keys , val ;
46
- var attrUpdate = { } ;
47
- var attrIndices = [ ] ;
53
+ var dataUpdate = { } ;
54
+ var dataIndices = [ ] ;
48
55
var carrs = [ ] ;
49
56
var carrIdx = [ ] ;
50
57
51
- function insertUpdate ( traceIndex , key , value ) {
52
- var attrIndex = attrIndices . indexOf ( traceIndex ) ;
53
- var valueArray = attrUpdate [ key ] ;
58
+ function insertDataUpdate ( traceIndex , value ) {
59
+ var attrIndex = dataIndices . indexOf ( traceIndex ) ;
60
+ var valueArray = dataUpdate . visible ;
54
61
if ( ! valueArray ) {
55
- valueArray = attrUpdate [ key ] = [ ] ;
62
+ valueArray = dataUpdate . visible = [ ] ;
56
63
}
57
64
58
- if ( attrIndices . indexOf ( traceIndex ) === - 1 ) {
59
- attrIndices . push ( traceIndex ) ;
60
- attrIndex = attrIndices . length - 1 ;
65
+ if ( dataIndices . indexOf ( traceIndex ) === - 1 ) {
66
+ dataIndices . push ( traceIndex ) ;
67
+ attrIndex = dataIndices . length - 1 ;
61
68
}
62
69
63
70
valueArray [ attrIndex ] = value ;
64
71
65
72
return attrIndex ;
66
73
}
67
74
75
+ var updatedShapes = ( fullLayout . shapes || [ ] ) . map ( function ( d ) {
76
+ return d . _input ;
77
+ } ) ;
78
+
79
+ var shapesUpdated = false ;
80
+
81
+ function insertShapesUpdate ( shapeIndex , value ) {
82
+ updatedShapes [ shapeIndex ] . visible = value ;
83
+ shapesUpdated = true ;
84
+ }
85
+
68
86
function setVisibility ( fullTrace , visibility ) {
69
87
if ( legendItem . groupTitle && ! toggleGroup ) return ;
70
88
71
- var fullInput = fullTrace . _fullInput ;
89
+ var fullInput = fullTrace . _fullInput || fullTrace ;
90
+ var isShape = fullInput . _isShape ;
91
+ var index = fullInput . index ;
92
+ if ( index === undefined ) index = fullInput . _index ;
93
+
72
94
if ( Registry . hasTransform ( fullInput , 'groupby' ) ) {
73
- var kcont = carrs [ fullInput . index ] ;
95
+ var kcont = carrs [ index ] ;
74
96
if ( ! kcont ) {
75
97
var groupbyIndices = Registry . getTransformIndices ( fullInput , 'groupby' ) ;
76
98
var lastGroupbyIndex = groupbyIndices [ groupbyIndices . length - 1 ] ;
77
99
kcont = Lib . keyedContainer ( fullInput , 'transforms[' + lastGroupbyIndex + '].styles' , 'target' , 'value.visible' ) ;
78
- carrs [ fullInput . index ] = kcont ;
100
+ carrs [ index ] = kcont ;
79
101
}
80
102
81
103
var curState = kcont . get ( fullTrace . _group ) ;
@@ -93,20 +115,27 @@ module.exports = function handleClick(g, gd, numClicks) {
93
115
// true -> legendonly. All others toggle to true:
94
116
kcont . set ( fullTrace . _group , visibility ) ;
95
117
}
96
- carrIdx [ fullInput . index ] = insertUpdate ( fullInput . index , 'visible' , fullInput . visible === false ? false : true ) ;
118
+ carrIdx [ index ] = insertDataUpdate ( index , fullInput . visible === false ? false : true ) ;
97
119
} else {
98
120
// false -> false (not possible since will not be visible in legend)
99
121
// true -> legendonly
100
122
// legendonly -> true
101
123
var nextVisibility = fullInput . visible === false ? false : visibility ;
102
124
103
- insertUpdate ( fullInput . index , 'visible' , nextVisibility ) ;
125
+ if ( isShape ) {
126
+ insertShapesUpdate ( index , nextVisibility ) ;
127
+ } else {
128
+ insertDataUpdate ( index , nextVisibility ) ;
129
+ }
104
130
}
105
131
}
106
132
107
133
var thisLegend = fullTrace . legend ;
108
134
109
- if ( Registry . traceIs ( fullTrace , 'pie-like' ) ) {
135
+ var fullInput = fullTrace . _fullInput ;
136
+ var isShape = fullInput && fullInput . _isShape ;
137
+
138
+ if ( ! isShape && Registry . traceIs ( fullTrace , 'pie-like' ) ) {
110
139
var thisLabel = legendItem . label ;
111
140
var thisLabelIndex = hiddenSlices . indexOf ( thisLabel ) ;
112
141
@@ -149,8 +178,8 @@ module.exports = function handleClick(g, gd, numClicks) {
149
178
var traceIndicesInGroup = [ ] ;
150
179
var tracei ;
151
180
if ( hasLegendgroup ) {
152
- for ( i = 0 ; i < fullData . length ; i ++ ) {
153
- tracei = fullData [ i ] ;
181
+ for ( i = 0 ; i < allLegendItems . length ; i ++ ) {
182
+ tracei = allLegendItems [ i ] ;
154
183
if ( ! tracei . visible ) continue ;
155
184
if ( tracei . legendgroup === legendgroup ) {
156
185
traceIndicesInGroup . push ( i ) ;
@@ -175,9 +204,10 @@ module.exports = function handleClick(g, gd, numClicks) {
175
204
176
205
if ( hasLegendgroup ) {
177
206
if ( toggleGroup ) {
178
- for ( i = 0 ; i < fullData . length ; i ++ ) {
179
- if ( fullData [ i ] . visible !== false && fullData [ i ] . legendgroup === legendgroup ) {
180
- setVisibility ( fullData [ i ] , nextVisibility ) ;
207
+ for ( i = 0 ; i < allLegendItems . length ; i ++ ) {
208
+ var item = allLegendItems [ i ] ;
209
+ if ( item . visible !== false && item . legendgroup === legendgroup ) {
210
+ setVisibility ( item , nextVisibility ) ;
181
211
}
182
212
}
183
213
} else {
@@ -189,40 +219,43 @@ module.exports = function handleClick(g, gd, numClicks) {
189
219
} else if ( mode === 'toggleothers' ) {
190
220
// Compute the clicked index. expandedIndex does what we want for expanded traces
191
221
// but also culls hidden traces. That means we have some work to do.
192
- var isClicked , isInGroup , notInLegend , otherState ;
222
+ var isClicked , isInGroup , notInLegend , otherState , _item ;
193
223
var isIsolated = true ;
194
- for ( i = 0 ; i < fullData . length ; i ++ ) {
195
- isClicked = fullData [ i ] === fullTrace ;
196
- notInLegend = fullData [ i ] . showlegend !== true ;
224
+ for ( i = 0 ; i < allLegendItems . length ; i ++ ) {
225
+ _item = allLegendItems [ i ] ;
226
+ isClicked = _item === fullTrace ;
227
+ notInLegend = _item . showlegend !== true ;
197
228
if ( isClicked || notInLegend ) continue ;
198
229
199
- isInGroup = ( hasLegendgroup && fullData [ i ] . legendgroup === legendgroup ) ;
230
+ isInGroup = ( hasLegendgroup && _item . legendgroup === legendgroup ) ;
200
231
201
- if ( fullData [ i ] . legend === thisLegend && ! isInGroup && fullData [ i ] . visible === true && ! Registry . traceIs ( fullData [ i ] , 'notLegendIsolatable' ) ) {
232
+ if ( ! isInGroup && _item . legend === thisLegend && _item . visible === true && ! Registry . traceIs ( _item , 'notLegendIsolatable' ) ) {
202
233
isIsolated = false ;
203
234
break ;
204
235
}
205
236
}
206
237
207
- for ( i = 0 ; i < fullData . length ; i ++ ) {
238
+ for ( i = 0 ; i < allLegendItems . length ; i ++ ) {
239
+ _item = allLegendItems [ i ] ;
240
+
208
241
// False is sticky; we don't change it. Also ensure we don't change states of itmes in other legend
209
- if ( fullData [ i ] . visible === false || fullData [ i ] . legend !== thisLegend ) continue ;
242
+ if ( _item . visible === false || _item . legend !== thisLegend ) continue ;
210
243
211
- if ( Registry . traceIs ( fullData [ i ] , 'notLegendIsolatable' ) ) {
244
+ if ( Registry . traceIs ( _item , 'notLegendIsolatable' ) ) {
212
245
continue ;
213
246
}
214
247
215
248
switch ( fullTrace . visible ) {
216
249
case 'legendonly' :
217
- setVisibility ( fullData [ i ] , true ) ;
250
+ setVisibility ( _item , true ) ;
218
251
break ;
219
252
case true :
220
253
otherState = isIsolated ? true : 'legendonly' ;
221
- isClicked = fullData [ i ] === fullTrace ;
254
+ isClicked = _item === fullTrace ;
222
255
// N.B. consider traces that have a set legendgroup as toggleable
223
- notInLegend = ( fullData [ i ] . showlegend !== true && ! fullData [ i ] . legendgroup ) ;
224
- isInGroup = isClicked || ( hasLegendgroup && fullData [ i ] . legendgroup === legendgroup ) ;
225
- setVisibility ( fullData [ i ] , ( isInGroup || notInLegend ) ? true : otherState ) ;
256
+ notInLegend = ( _item . showlegend !== true && ! _item . legendgroup ) ;
257
+ isInGroup = isClicked || ( hasLegendgroup && _item . legendgroup === legendgroup ) ;
258
+ setVisibility ( _item , ( isInGroup || notInLegend ) ? true : otherState ) ;
226
259
break ;
227
260
}
228
261
}
@@ -236,7 +269,7 @@ module.exports = function handleClick(g, gd, numClicks) {
236
269
var updateKeys = Object . keys ( update ) ;
237
270
for ( j = 0 ; j < updateKeys . length ; j ++ ) {
238
271
key = updateKeys [ j ] ;
239
- val = attrUpdate [ key ] = attrUpdate [ key ] || [ ] ;
272
+ val = dataUpdate [ key ] = dataUpdate [ key ] || [ ] ;
240
273
val [ carrIdx [ i ] ] = update [ key ] ;
241
274
}
242
275
}
@@ -245,17 +278,21 @@ module.exports = function handleClick(g, gd, numClicks) {
245
278
// values should be explicitly undefined for them to get properly culled
246
279
// as updates and not accidentally reset to the default value. This fills
247
280
// out sparse arrays with the required number of undefined values:
248
- keys = Object . keys ( attrUpdate ) ;
281
+ keys = Object . keys ( dataUpdate ) ;
249
282
for ( i = 0 ; i < keys . length ; i ++ ) {
250
283
key = keys [ i ] ;
251
- for ( j = 0 ; j < attrIndices . length ; j ++ ) {
284
+ for ( j = 0 ; j < dataIndices . length ; j ++ ) {
252
285
// Use hasOwnProperty to protect against falsy values:
253
- if ( ! attrUpdate [ key ] . hasOwnProperty ( j ) ) {
254
- attrUpdate [ key ] [ j ] = undefined ;
286
+ if ( ! dataUpdate [ key ] . hasOwnProperty ( j ) ) {
287
+ dataUpdate [ key ] [ j ] = undefined ;
255
288
}
256
289
}
257
290
}
258
291
259
- Registry . call ( '_guiRestyle' , gd , attrUpdate , attrIndices ) ;
292
+ if ( shapesUpdated ) {
293
+ Registry . call ( '_guiUpdate' , gd , dataUpdate , { shapes : updatedShapes } , dataIndices ) ;
294
+ } else {
295
+ Registry . call ( '_guiRestyle' , gd , dataUpdate , dataIndices ) ;
296
+ }
260
297
}
261
298
} ;
0 commit comments