@@ -28,6 +28,8 @@ define([
28
28
'properties'
29
29
] , function ( wreqr , $ , _ , Marionette , CustomElements , template , Plotly , Property , PropertyView , metacardDefinitions , Common , properties ) {
30
30
31
+ var zeroWidthSpace = "\u200B" ;
32
+
31
33
function calculateAvailableAttributes ( results ) {
32
34
var availableAttributes = [ ] ;
33
35
results . forEach ( function ( result ) {
@@ -91,13 +93,12 @@ define([
91
93
switch ( metacardDefinitions . metacardTypes [ attribute ] . type ) {
92
94
case 'DATE' :
93
95
return values . indexOf ( Common . getHumanReadableDate ( value ) ) >= 0 ;
94
- break ;
96
+ case 'BOOLEAN' :
97
+ case 'STRING' :
98
+ return values . indexOf ( value . toString ( ) + zeroWidthSpace ) >= 0 ;
95
99
default :
96
- return values . indexOf ( value . toString ( ) ) >= 0 ;
97
- break ;
100
+ return value >= values [ 0 ] && value <= values [ 1 ] ;
98
101
}
99
- } else {
100
- return values . indexOf ( "" ) >= 0 ;
101
102
}
102
103
}
103
104
@@ -107,41 +108,67 @@ define([
107
108
case 'DATE' :
108
109
valueArray . push ( Common . getHumanReadableDate ( value ) ) ;
109
110
break ;
111
+ case 'BOOLEAN' :
112
+ case 'STRING' :
113
+ valueArray . push ( value . toString ( ) + zeroWidthSpace ) ;
114
+ break ;
110
115
default :
111
- valueArray . push ( value . toString ( ) ) ;
116
+ valueArray . push ( parseFloat ( value ) ) ;
112
117
break ;
113
118
}
119
+ }
120
+ }
121
+
122
+ function getIndexClicked ( data ) {
123
+ return Math . max . apply ( this , data . points . map ( function ( point ) {
124
+ return point . pointNumber ;
125
+ } ) ) ;
126
+ }
127
+
128
+ function getValueFromClick ( data ) {
129
+ if ( data . points [ 0 ] . x . constructor === Number ) {
130
+ var spread = data . points [ 0 ] . data . xbins . size * 0.5 ;
131
+ return [ data . points [ 0 ] . x - spread , data . points [ 0 ] . x + spread ] ;
114
132
} else {
115
- valueArray . push ( "" ) ;
133
+ return [ data . points [ 0 ] . x ] ;
116
134
}
117
135
}
118
136
119
- var layout = {
120
- autosize : true ,
121
- paper_bgcolor :'rgba(0,0,0,0)' ,
122
- plot_bgcolor : 'rgba(0,0,0,0)' ,
123
- font : {
124
- family : '"Open Sans Light","Helvetica Neue",Helvetica,Arial,sans-serif' ,
125
- size : 18 ,
126
- color : 'white'
127
- } ,
128
- margin : {
129
- l : 100 ,
130
- r : 100 ,
131
- t : 100 ,
132
- b : 200 ,
133
- pad : 20 ,
134
- autoexpand : true
135
- } ,
136
- barmode : 'overlay' ,
137
- xaxis : {
138
- fixedrange : true
139
- } ,
140
- yaxis : {
141
- fixedrange : true
142
- } ,
143
- showlegend : true
144
- } ;
137
+ function getLayout ( plot ) {
138
+ var baseLayout = {
139
+ autosize : true ,
140
+ paper_bgcolor :'rgba(0,0,0,0)' ,
141
+ plot_bgcolor : 'rgba(0,0,0,0)' ,
142
+ font : {
143
+ family : '"Open Sans Light","Helvetica Neue",Helvetica,Arial,sans-serif' ,
144
+ size : 18 ,
145
+ color : 'white'
146
+ } ,
147
+ margin : {
148
+ l : 100 ,
149
+ r : 100 ,
150
+ t : 100 ,
151
+ b : 200 ,
152
+ pad : 20 ,
153
+ autoexpand : true
154
+ } ,
155
+ barmode : 'overlay' ,
156
+ xaxis : {
157
+ fixedrange : true
158
+ } ,
159
+ yaxis : {
160
+ fixedrange : true
161
+ } ,
162
+ showlegend : true
163
+ } ;
164
+ if ( plot ) {
165
+ baseLayout . xaxis . autorange = false ;
166
+ baseLayout . xaxis . range = plot . _fullLayout . xaxis . range ;
167
+ baseLayout . yaxis . range = plot . _fullLayout . yaxis . range ;
168
+ baseLayout . yaxis . autorange = false ;
169
+ }
170
+ return baseLayout ;
171
+ }
145
172
146
173
return Marionette . LayoutView . extend ( {
147
174
tagName : CustomElements . register ( 'histogram' ) ,
@@ -158,13 +185,18 @@ define([
158
185
this . setupListeners ( ) ;
159
186
} ,
160
187
showHistogram : function ( ) {
161
- if ( this . histogramAttribute . currentView . getCurrentValue ( ) [ 0 ] ) {
188
+ if ( this . histogramAttribute . currentView . getCurrentValue ( ) [ 0 ] && this . options . selectionInterface . getActiveSearchResults ( ) . length !== 0 ) {
162
189
var histogramElement = this . el . querySelector ( '.histogram-container' ) ;
163
- Plotly . newPlot ( histogramElement , this . determineData ( ) , layout , {
190
+ //Plotly.purge(histogramElement);
191
+ Plotly . newPlot ( histogramElement , this . determineInitialData ( ) , getLayout ( ) , {
164
192
displayModeBar : false
165
- } ) ;
166
- this . handleResize ( ) ;
167
- this . listenToHistogram ( ) ;
193
+ } ) . then ( function ( plot ) {
194
+ Plotly . newPlot ( histogramElement , this . determineData ( plot ) , getLayout ( plot ) , {
195
+ displayModeBar : false
196
+ } ) ;
197
+ this . handleResize ( ) ;
198
+ this . listenToHistogram ( ) ;
199
+ } . bind ( this ) ) ;
168
200
} else {
169
201
this . el . querySelector ( '.histogram-container' ) . innerHTML = '' ;
170
202
}
@@ -191,10 +223,29 @@ define([
191
223
this . showHistogram ( ) ;
192
224
this . handleEmpty ( ) ;
193
225
} ,
194
- determineData : function ( ) {
226
+ determineInitialData : function ( ) {
227
+ var activeResults = this . options . selectionInterface . getActiveSearchResults ( ) ;
228
+ return [
229
+ {
230
+ x : calculateAttributeArray ( activeResults , this . histogramAttribute . currentView . getCurrentValue ( ) [ 0 ] ) ,
231
+ opacity : 1 ,
232
+ type : 'histogram' ,
233
+ name : 'Hits ' ,
234
+ marker : {
235
+ color : 'rgba(255, 255, 255, .05)' ,
236
+ line : {
237
+ color : 'rgba(255,255,255,.2)' ,
238
+ width : '2'
239
+ }
240
+ }
241
+ }
242
+ ] ;
243
+ } ,
244
+ determineData : function ( plot ) {
195
245
var activeResults = this . options . selectionInterface . getActiveSearchResults ( ) ;
196
246
var selectedResults = this . options . selectionInterface . getSelectedResults ( ) ;
197
-
247
+ var xbins = Common . duplicate ( plot . _fullData [ 0 ] . xbins ) ;
248
+ xbins . end = xbins . end + xbins . size ; //https://github.com/plotly/plotly.js/issues/1229
198
249
return [
199
250
{
200
251
x : calculateAttributeArray ( activeResults , this . histogramAttribute . currentView . getCurrentValue ( ) [ 0 ] ) ,
@@ -207,15 +258,19 @@ define([
207
258
color : 'rgba(255,255,255,.2)' ,
208
259
width : '2'
209
260
}
210
- }
261
+ } ,
262
+ autobinx : false ,
263
+ xbins : xbins
211
264
} , {
212
265
x : calculateAttributeArray ( selectedResults , this . histogramAttribute . currentView . getCurrentValue ( ) [ 0 ] ) ,
213
266
opacity : 1 ,
214
267
type : 'histogram' ,
215
268
name : 'Selected' ,
216
269
marker : {
217
270
color : 'rgba(255, 255, 255, .2)'
218
- }
271
+ } ,
272
+ autobinx : false ,
273
+ xbins : xbins
219
274
}
220
275
]
221
276
@@ -258,7 +313,8 @@ define([
258
313
this . el . querySelector ( '.histogram-container' ) . on ( 'plotly_click' , this . plotlyClickHandler . bind ( this ) ) ;
259
314
} ,
260
315
plotlyClickHandler : function ( data ) {
261
- var alreadySelected = this . pointsSelected . indexOf ( data . points [ 0 ] . pointNumber ) >= 0 ;
316
+ var indexClicked = getIndexClicked ( data ) ;
317
+ var alreadySelected = this . pointsSelected . indexOf ( indexClicked ) >= 0 ;
262
318
if ( this . shiftKey ) {
263
319
this . handleShiftClick ( data ) ;
264
320
} else if ( this . ctrlKey || this . metaKey ) {
@@ -276,24 +332,20 @@ define([
276
332
this . options . selectionInterface . removeSelectedResult ( findMatchesForAttributeValues (
277
333
this . options . selectionInterface . getActiveSearchResults ( ) ,
278
334
attributeToCheck ,
279
- [ data . points [ 0 ] . x ]
335
+ getValueFromClick ( data )
280
336
) ) ;
281
- this . pointsSelected . splice ( this . pointsSelected . indexOf ( data . points [ 0 ] . pointNumber ) , 1 ) ;
337
+ this . pointsSelected . splice ( this . pointsSelected . indexOf ( getIndexClicked ( data ) ) , 1 ) ;
282
338
} else {
283
339
this . options . selectionInterface . addSelectedResult ( findMatchesForAttributeValues (
284
340
this . options . selectionInterface . getActiveSearchResults ( ) ,
285
341
attributeToCheck ,
286
- [ data . points [ 0 ] . x ]
342
+ getValueFromClick ( data )
287
343
) ) ;
288
- this . pointsSelected . push ( Math . max . apply ( this , data . points . map ( function ( point ) {
289
- return point . pointNumber ;
290
- } ) ) ) ;
344
+ this . pointsSelected . push ( getIndexClicked ( data ) ) ;
291
345
}
292
346
} ,
293
347
handleShiftClick : function ( data , alreadySelected ) {
294
- var indexClicked = Math . max . apply ( this , data . points . map ( function ( point ) {
295
- return point . pointNumber ;
296
- } ) ) ;
348
+ var indexClicked = getIndexClicked ( data ) ;
297
349
var firstIndex = this . pointsSelected . length === 0 ? - 1 : this . pointsSelected . reduce ( function ( currentMin , point ) {
298
350
return Math . min ( currentMin , point ) ;
299
351
} , this . pointsSelected [ 0 ] ) ;
@@ -312,19 +364,44 @@ define([
312
364
}
313
365
} ,
314
366
selectBetween : function ( firstIndex , lastIndex ) {
367
+ for ( var i = firstIndex ; i <= lastIndex ; i ++ ) {
368
+ if ( this . pointsSelected . indexOf ( i ) === - 1 ) {
369
+ this . pointsSelected . push ( i ) ;
370
+ }
371
+ }
315
372
var attributeToCheck = this . histogramAttribute . currentView . getCurrentValue ( ) [ 0 ] ;
316
373
var categories = this . retrieveCategoriesFromPlotly ( ) ;
317
374
var validCategories = categories . slice ( firstIndex , lastIndex ) ;
318
- this . options . selectionInterface . addSelectedResult ( findMatchesForAttributeValues (
319
- this . options . selectionInterface . getActiveSearchResults ( ) ,
320
- attributeToCheck ,
321
- validCategories
322
- ) ) ;
375
+ var activeSearchResults = this . options . selectionInterface . getActiveSearchResults ( ) ;
376
+ this . options . selectionInterface . addSelectedResult ( validCategories . reduce ( function ( results , category ) {
377
+ results = results . concat ( findMatchesForAttributeValues (
378
+ activeSearchResults ,
379
+ attributeToCheck ,
380
+ category . constructor === Array ? category : [ category ]
381
+ ) ) ;
382
+ return results ;
383
+ } , [ ] ) ) ;
323
384
} ,
385
+ // This is an internal variable for Plotly, so it might break if we update Plotly in the future.
386
+ // Regardless, there was no other way to reliably get the categories.
324
387
retrieveCategoriesFromPlotly : function ( ) {
325
- // This is an internal variable for Plotly, so it might break if we update Plotly in the future.
326
- // Regardless, there was no other way to reliably get the categories.
327
- return this . el . querySelector ( '.histogram-container' ) . _fullLayout . xaxis . _categories ;
388
+ var histogramElement = this . el . querySelector ( '.histogram-container' ) ;
389
+ var xaxis = histogramElement . _fullLayout . xaxis ;
390
+ if ( xaxis . _categories . length > 0 ) {
391
+ return xaxis . _categories ;
392
+ } else {
393
+ var xbins = histogramElement . _fullData [ 0 ] . xbins ;
394
+ var min = xbins . start ;
395
+ var max = xbins . end ;
396
+ var binSize = xbins . size ;
397
+ var categories = [ ] ;
398
+ var start = min ;
399
+ while ( start < max ) {
400
+ categories . push ( [ start , start + binSize ] ) ;
401
+ start += binSize ;
402
+ }
403
+ return categories ;
404
+ }
328
405
} ,
329
406
resetKeyTracking : function ( ) {
330
407
this . shiftKey = false ;
0 commit comments