@@ -83,7 +83,6 @@ proto.plot = function(calcData, fullLayout, promises) {
83
83
84
84
proto . createMap = function ( calcData , fullLayout , resolve , reject ) {
85
85
var self = this ;
86
- var gd = self . gd ;
87
86
var opts = fullLayout [ self . id ] ;
88
87
89
88
// store style id and URL or object
@@ -115,6 +114,10 @@ proto.createMap = function(calcData, fullLayout, resolve, reject) {
115
114
116
115
self . rejectOnError ( reject ) ;
117
116
117
+ if ( ! self . isStatic ) {
118
+ self . initFx ( calcData , fullLayout ) ;
119
+ }
120
+
118
121
var promises = [ ] ;
119
122
120
123
promises . push ( new Promise ( function ( resolve ) {
@@ -127,121 +130,7 @@ proto.createMap = function(calcData, fullLayout, resolve, reject) {
127
130
self . updateData ( calcData ) ;
128
131
self . updateLayout ( fullLayout ) ;
129
132
self . resolveOnRender ( resolve ) ;
130
- } ) ;
131
-
132
- if ( self . isStatic ) return ;
133
-
134
- var wheeling = false ;
135
-
136
- // keep track of pan / zoom in user layout and emit relayout event
137
- map . on ( 'moveend' , function ( eventData ) {
138
- if ( ! self . map ) return ;
139
-
140
- // 'moveend' gets triggered by map.setCenter, map.setZoom,
141
- // map.setBearing and map.setPitch.
142
- //
143
- // Here, we make sure that state updates amd 'plotly_relayout'
144
- // are triggered only when the 'moveend' originates from a
145
- // mouse target (filtering out API calls) to not
146
- // duplicate 'plotly_relayout' events.
147
-
148
- if ( eventData . originalEvent || wheeling ) {
149
- var optsNow = gd . _fullLayout [ self . id ] ;
150
- Registry . call ( '_storeDirectGUIEdit' , gd . layout , gd . _fullLayout . _preGUI , self . getViewEdits ( optsNow ) ) ;
151
-
152
- var viewNow = self . getView ( ) ;
153
- optsNow . _input . center = optsNow . center = viewNow . center ;
154
- optsNow . _input . zoom = optsNow . zoom = viewNow . zoom ;
155
- optsNow . _input . bearing = optsNow . bearing = viewNow . bearing ;
156
- optsNow . _input . pitch = optsNow . pitch = viewNow . pitch ;
157
-
158
- gd . emit ( 'plotly_relayout' , self . getViewEdits ( viewNow ) ) ;
159
- }
160
- wheeling = false ;
161
- } ) ;
162
-
163
- map . on ( 'wheel' , function ( ) {
164
- wheeling = true ;
165
- } ) ;
166
-
167
- map . on ( 'mousemove' , function ( evt ) {
168
- var bb = self . div . getBoundingClientRect ( ) ;
169
-
170
- // some hackery to get Fx.hover to work
171
- evt . clientX = evt . point . x + bb . left ;
172
- evt . clientY = evt . point . y + bb . top ;
173
-
174
- evt . target . getBoundingClientRect = function ( ) { return bb ; } ;
175
-
176
- self . xaxis . p2c = function ( ) { return evt . lngLat . lng ; } ;
177
- self . yaxis . p2c = function ( ) { return evt . lngLat . lat ; } ;
178
-
179
- Fx . hover ( gd , evt , self . id ) ;
180
- } ) ;
181
-
182
- function unhover ( ) {
183
- Fx . loneUnhover ( fullLayout . _toppaper ) ;
184
- }
185
-
186
- map . on ( 'dragstart' , unhover ) ;
187
- map . on ( 'zoomstart' , unhover ) ;
188
-
189
- function emitUpdate ( ) {
190
- var viewNow = self . getView ( ) ;
191
- gd . emit ( 'plotly_relayouting' , self . getViewEdits ( viewNow ) ) ;
192
- }
193
-
194
- map . on ( 'drag' , emitUpdate ) ;
195
- map . on ( 'zoom' , emitUpdate ) ;
196
-
197
- map . on ( 'dblclick' , function ( ) {
198
- var optsNow = gd . _fullLayout [ self . id ] ;
199
- Registry . call ( '_storeDirectGUIEdit' , gd . layout , gd . _fullLayout . _preGUI , self . getViewEdits ( optsNow ) ) ;
200
-
201
- var viewInitial = self . viewInitial ;
202
- map . setCenter ( convertCenter ( viewInitial . center ) ) ;
203
- map . setZoom ( viewInitial . zoom ) ;
204
- map . setBearing ( viewInitial . bearing ) ;
205
- map . setPitch ( viewInitial . pitch ) ;
206
-
207
- var viewNow = self . getView ( ) ;
208
- optsNow . _input . center = optsNow . center = viewNow . center ;
209
- optsNow . _input . zoom = optsNow . zoom = viewNow . zoom ;
210
- optsNow . _input . bearing = optsNow . bearing = viewNow . bearing ;
211
- optsNow . _input . pitch = optsNow . pitch = viewNow . pitch ;
212
-
213
- gd . emit ( 'plotly_doubleclick' , null ) ;
214
- gd . emit ( 'plotly_relayout' , self . getViewEdits ( viewNow ) ) ;
215
- } ) ;
216
-
217
- // define event handlers on map creation, to keep one ref per map,
218
- // so that map.on / map.off in updateFx works as expected
219
- self . clearSelect = function ( ) {
220
- gd . _fullLayout . _zoomlayer . selectAll ( '.select-outline' ) . remove ( ) ;
221
- } ;
222
-
223
- /**
224
- * Returns a click handler function that is supposed
225
- * to handle clicks in pan mode.
226
- */
227
- self . onClickInPanFn = function ( dragOptions ) {
228
- return function ( evt ) {
229
- var clickMode = gd . _fullLayout . clickmode ;
230
-
231
- if ( clickMode . indexOf ( 'select' ) > - 1 ) {
232
- selectOnClick ( evt . originalEvent , gd , [ self . xaxis ] , [ self . yaxis ] , self . id , dragOptions ) ;
233
- }
234
-
235
- if ( clickMode . indexOf ( 'event' ) > - 1 ) {
236
- // TODO: this does not support right-click. If we want to support it, we
237
- // would likely need to change mapbox to use dragElement instead of straight
238
- // mapbox event binding. Or perhaps better, make a simple wrapper with the
239
- // right mousedown, mousemove, and mouseup handlers just for a left/right click
240
- // pie would use this too.
241
- Fx . click ( gd , evt . originalEvent ) ;
242
- }
243
- } ;
244
- } ;
133
+ } ) . catch ( reject ) ;
245
134
} ;
246
135
247
136
proto . fetchMapData = function ( calcData ) {
@@ -251,6 +140,7 @@ proto.fetchMapData = function(calcData) {
251
140
return new Promise ( function ( resolve , reject ) {
252
141
d3 . json ( url , function ( err , d ) {
253
142
if ( err ) {
143
+ delete PlotlyGeoAssets [ url ] ;
254
144
var msg = err . status === 404 ?
255
145
( 'GeoJSON at URL ' + url + ' does not exist.' ) :
256
146
( 'Unexpected error while fetching from ' + url ) ;
@@ -305,7 +195,7 @@ proto.updateMap = function(calcData, fullLayout, resolve, reject) {
305
195
self . updateData ( calcData ) ;
306
196
self . updateLayout ( fullLayout ) ;
307
197
self . resolveOnRender ( resolve ) ;
308
- } ) ;
198
+ } ) . catch ( reject ) ;
309
199
} ;
310
200
311
201
var traceType2orderIndex = {
@@ -431,6 +321,141 @@ proto.createFramework = function(fullLayout) {
431
321
Axes . setConvert ( self . mockAxis , fullLayout ) ;
432
322
} ;
433
323
324
+ proto . initFx = function ( calcData , fullLayout ) {
325
+ var self = this ;
326
+ var gd = self . gd ;
327
+ var map = self . map ;
328
+
329
+ var wheeling = false ;
330
+
331
+ // keep track of pan / zoom in user layout and emit relayout event
332
+ map . on ( 'moveend' , function ( evt ) {
333
+ if ( ! self . map ) return ;
334
+
335
+ var fullLayoutNow = gd . _fullLayout ;
336
+
337
+ // 'moveend' gets triggered by map.setCenter, map.setZoom,
338
+ // map.setBearing and map.setPitch.
339
+ //
340
+ // Here, we make sure that state updates amd 'plotly_relayout'
341
+ // are triggered only when the 'moveend' originates from a
342
+ // mouse target (filtering out API calls) to not
343
+ // duplicate 'plotly_relayout' events.
344
+
345
+ if ( evt . originalEvent || wheeling ) {
346
+ var optsNow = fullLayoutNow [ self . id ] ;
347
+ Registry . call ( '_storeDirectGUIEdit' , gd . layout , fullLayoutNow . _preGUI , self . getViewEdits ( optsNow ) ) ;
348
+
349
+ var viewNow = self . getView ( ) ;
350
+ optsNow . _input . center = optsNow . center = viewNow . center ;
351
+ optsNow . _input . zoom = optsNow . zoom = viewNow . zoom ;
352
+ optsNow . _input . bearing = optsNow . bearing = viewNow . bearing ;
353
+ optsNow . _input . pitch = optsNow . pitch = viewNow . pitch ;
354
+
355
+ gd . emit ( 'plotly_relayout' , self . getViewEdits ( viewNow ) ) ;
356
+ }
357
+ wheeling = false ;
358
+
359
+ if ( fullLayoutNow . _rehover ) {
360
+ fullLayoutNow . _rehover ( ) ;
361
+ }
362
+ } ) ;
363
+
364
+ map . on ( 'wheel' , function ( ) {
365
+ wheeling = true ;
366
+ } ) ;
367
+
368
+ map . on ( 'mousemove' , function ( evt ) {
369
+ var bb = self . div . getBoundingClientRect ( ) ;
370
+
371
+ // some hackery to get Fx.hover to work
372
+ evt . clientX = evt . point . x + bb . left ;
373
+ evt . clientY = evt . point . y + bb . top ;
374
+
375
+ evt . target . getBoundingClientRect = function ( ) { return bb ; } ;
376
+
377
+ self . xaxis . p2c = function ( ) { return evt . lngLat . lng ; } ;
378
+ self . yaxis . p2c = function ( ) { return evt . lngLat . lat ; } ;
379
+
380
+ gd . _fullLayout . _rehover = function ( ) {
381
+ if ( gd . _fullLayout . _hoversubplot === self . id ) {
382
+ Fx . hover ( gd , evt , self . id ) ;
383
+ }
384
+ } ;
385
+
386
+ Fx . hover ( gd , evt , self . id ) ;
387
+ gd . _fullLayout . _hoversubplot = self . id ;
388
+ } ) ;
389
+
390
+ function unhover ( ) {
391
+ Fx . loneUnhover ( fullLayout . _hoverlayer ) ;
392
+ }
393
+
394
+ map . on ( 'dragstart' , unhover ) ;
395
+ map . on ( 'zoomstart' , unhover ) ;
396
+
397
+ map . on ( 'mouseout' , function ( ) {
398
+ gd . _fullLayout . _hoversubplot = null ;
399
+ } ) ;
400
+
401
+ function emitUpdate ( ) {
402
+ var viewNow = self . getView ( ) ;
403
+ gd . emit ( 'plotly_relayouting' , self . getViewEdits ( viewNow ) ) ;
404
+ }
405
+
406
+ map . on ( 'drag' , emitUpdate ) ;
407
+ map . on ( 'zoom' , emitUpdate ) ;
408
+
409
+ map . on ( 'dblclick' , function ( ) {
410
+ var optsNow = gd . _fullLayout [ self . id ] ;
411
+ Registry . call ( '_storeDirectGUIEdit' , gd . layout , gd . _fullLayout . _preGUI , self . getViewEdits ( optsNow ) ) ;
412
+
413
+ var viewInitial = self . viewInitial ;
414
+ map . setCenter ( convertCenter ( viewInitial . center ) ) ;
415
+ map . setZoom ( viewInitial . zoom ) ;
416
+ map . setBearing ( viewInitial . bearing ) ;
417
+ map . setPitch ( viewInitial . pitch ) ;
418
+
419
+ var viewNow = self . getView ( ) ;
420
+ optsNow . _input . center = optsNow . center = viewNow . center ;
421
+ optsNow . _input . zoom = optsNow . zoom = viewNow . zoom ;
422
+ optsNow . _input . bearing = optsNow . bearing = viewNow . bearing ;
423
+ optsNow . _input . pitch = optsNow . pitch = viewNow . pitch ;
424
+
425
+ gd . emit ( 'plotly_doubleclick' , null ) ;
426
+ gd . emit ( 'plotly_relayout' , self . getViewEdits ( viewNow ) ) ;
427
+ } ) ;
428
+
429
+ // define event handlers on map creation, to keep one ref per map,
430
+ // so that map.on / map.off in updateFx works as expected
431
+ self . clearSelect = function ( ) {
432
+ gd . _fullLayout . _zoomlayer . selectAll ( '.select-outline' ) . remove ( ) ;
433
+ } ;
434
+
435
+ /**
436
+ * Returns a click handler function that is supposed
437
+ * to handle clicks in pan mode.
438
+ */
439
+ self . onClickInPanFn = function ( dragOptions ) {
440
+ return function ( evt ) {
441
+ var clickMode = gd . _fullLayout . clickmode ;
442
+
443
+ if ( clickMode . indexOf ( 'select' ) > - 1 ) {
444
+ selectOnClick ( evt . originalEvent , gd , [ self . xaxis ] , [ self . yaxis ] , self . id , dragOptions ) ;
445
+ }
446
+
447
+ if ( clickMode . indexOf ( 'event' ) > - 1 ) {
448
+ // TODO: this does not support right-click. If we want to support it, we
449
+ // would likely need to change mapbox to use dragElement instead of straight
450
+ // mapbox event binding. Or perhaps better, make a simple wrapper with the
451
+ // right mousedown, mousemove, and mouseup handlers just for a left/right click
452
+ // pie would use this too.
453
+ Fx . click ( gd , evt . originalEvent ) ;
454
+ }
455
+ } ;
456
+ } ;
457
+ } ;
458
+
434
459
proto . updateFx = function ( fullLayout ) {
435
460
var self = this ;
436
461
var map = self . map ;
0 commit comments