@@ -39,43 +39,65 @@ module.exports = function handleClick(g, gd, numClicks) {
3939 if ( legendItem . groupTitle && legendItem . noClick ) return ;
4040
4141 var fullData = gd . _fullData ;
42+ var shapesWithLegend = ( fullLayout . shapes || [ ] ) . filter ( function ( d ) { return d . showlegend ; } ) ;
43+ var allLegendItems = fullData . concat ( shapesWithLegend ) ;
44+
4245 var fullTrace = legendItem . trace ;
46+ if ( fullTrace . _isShape ) {
47+ fullTrace = fullTrace . _fullInput ;
48+ }
49+
4350 var legendgroup = fullTrace . legendgroup ;
4451
4552 var i , j , kcont , key , keys , val ;
46- var attrUpdate = { } ;
47- var attrIndices = [ ] ;
53+ var dataUpdate = { } ;
54+ var dataIndices = [ ] ;
4855 var carrs = [ ] ;
4956 var carrIdx = [ ] ;
5057
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 ;
5461 if ( ! valueArray ) {
55- valueArray = attrUpdate [ key ] = [ ] ;
62+ valueArray = dataUpdate . visible = [ ] ;
5663 }
5764
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 ;
6168 }
6269
6370 valueArray [ attrIndex ] = value ;
6471
6572 return attrIndex ;
6673 }
6774
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+
6886 function setVisibility ( fullTrace , visibility ) {
6987 if ( legendItem . groupTitle && ! toggleGroup ) return ;
7088
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+
7294 if ( Registry . hasTransform ( fullInput , 'groupby' ) ) {
73- var kcont = carrs [ fullInput . index ] ;
95+ var kcont = carrs [ index ] ;
7496 if ( ! kcont ) {
7597 var groupbyIndices = Registry . getTransformIndices ( fullInput , 'groupby' ) ;
7698 var lastGroupbyIndex = groupbyIndices [ groupbyIndices . length - 1 ] ;
7799 kcont = Lib . keyedContainer ( fullInput , 'transforms[' + lastGroupbyIndex + '].styles' , 'target' , 'value.visible' ) ;
78- carrs [ fullInput . index ] = kcont ;
100+ carrs [ index ] = kcont ;
79101 }
80102
81103 var curState = kcont . get ( fullTrace . _group ) ;
@@ -93,20 +115,27 @@ module.exports = function handleClick(g, gd, numClicks) {
93115 // true -> legendonly. All others toggle to true:
94116 kcont . set ( fullTrace . _group , visibility ) ;
95117 }
96- carrIdx [ fullInput . index ] = insertUpdate ( fullInput . index , 'visible' , fullInput . visible === false ? false : true ) ;
118+ carrIdx [ index ] = insertDataUpdate ( index , fullInput . visible === false ? false : true ) ;
97119 } else {
98120 // false -> false (not possible since will not be visible in legend)
99121 // true -> legendonly
100122 // legendonly -> true
101123 var nextVisibility = fullInput . visible === false ? false : visibility ;
102124
103- insertUpdate ( fullInput . index , 'visible' , nextVisibility ) ;
125+ if ( isShape ) {
126+ insertShapesUpdate ( index , nextVisibility ) ;
127+ } else {
128+ insertDataUpdate ( index , nextVisibility ) ;
129+ }
104130 }
105131 }
106132
107133 var thisLegend = fullTrace . legend ;
108134
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' ) ) {
110139 var thisLabel = legendItem . label ;
111140 var thisLabelIndex = hiddenSlices . indexOf ( thisLabel ) ;
112141
@@ -149,8 +178,8 @@ module.exports = function handleClick(g, gd, numClicks) {
149178 var traceIndicesInGroup = [ ] ;
150179 var tracei ;
151180 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 ] ;
154183 if ( ! tracei . visible ) continue ;
155184 if ( tracei . legendgroup === legendgroup ) {
156185 traceIndicesInGroup . push ( i ) ;
@@ -175,9 +204,10 @@ module.exports = function handleClick(g, gd, numClicks) {
175204
176205 if ( hasLegendgroup ) {
177206 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 ) ;
181211 }
182212 }
183213 } else {
@@ -189,40 +219,43 @@ module.exports = function handleClick(g, gd, numClicks) {
189219 } else if ( mode === 'toggleothers' ) {
190220 // Compute the clicked index. expandedIndex does what we want for expanded traces
191221 // 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 ;
193223 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 ;
197228 if ( isClicked || notInLegend ) continue ;
198229
199- isInGroup = ( hasLegendgroup && fullData [ i ] . legendgroup === legendgroup ) ;
230+ isInGroup = ( hasLegendgroup && _item . legendgroup === legendgroup ) ;
200231
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' ) ) {
202233 isIsolated = false ;
203234 break ;
204235 }
205236 }
206237
207- for ( i = 0 ; i < fullData . length ; i ++ ) {
238+ for ( i = 0 ; i < allLegendItems . length ; i ++ ) {
239+ _item = allLegendItems [ i ] ;
240+
208241 // 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 ;
210243
211- if ( Registry . traceIs ( fullData [ i ] , 'notLegendIsolatable' ) ) {
244+ if ( Registry . traceIs ( _item , 'notLegendIsolatable' ) ) {
212245 continue ;
213246 }
214247
215248 switch ( fullTrace . visible ) {
216249 case 'legendonly' :
217- setVisibility ( fullData [ i ] , true ) ;
250+ setVisibility ( _item , true ) ;
218251 break ;
219252 case true :
220253 otherState = isIsolated ? true : 'legendonly' ;
221- isClicked = fullData [ i ] === fullTrace ;
254+ isClicked = _item === fullTrace ;
222255 // 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 ) ;
226259 break ;
227260 }
228261 }
@@ -236,7 +269,7 @@ module.exports = function handleClick(g, gd, numClicks) {
236269 var updateKeys = Object . keys ( update ) ;
237270 for ( j = 0 ; j < updateKeys . length ; j ++ ) {
238271 key = updateKeys [ j ] ;
239- val = attrUpdate [ key ] = attrUpdate [ key ] || [ ] ;
272+ val = dataUpdate [ key ] = dataUpdate [ key ] || [ ] ;
240273 val [ carrIdx [ i ] ] = update [ key ] ;
241274 }
242275 }
@@ -245,17 +278,21 @@ module.exports = function handleClick(g, gd, numClicks) {
245278 // values should be explicitly undefined for them to get properly culled
246279 // as updates and not accidentally reset to the default value. This fills
247280 // out sparse arrays with the required number of undefined values:
248- keys = Object . keys ( attrUpdate ) ;
281+ keys = Object . keys ( dataUpdate ) ;
249282 for ( i = 0 ; i < keys . length ; i ++ ) {
250283 key = keys [ i ] ;
251- for ( j = 0 ; j < attrIndices . length ; j ++ ) {
284+ for ( j = 0 ; j < dataIndices . length ; j ++ ) {
252285 // 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 ;
255288 }
256289 }
257290 }
258291
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+ }
260297 }
261298} ;
0 commit comments