@@ -438,6 +438,8 @@ plots.supplyDefaults = function(gd) {
438
438
} ;
439
439
newFullLayout . _traceWord = _ ( gd , 'trace' ) ;
440
440
441
+ var formatObj = getD3FormatObj ( gd ) ;
442
+
441
443
// first fill in what we can of layout without looking at data
442
444
// because fullData needs a few things from layout
443
445
@@ -447,15 +449,15 @@ plots.supplyDefaults = function(gd) {
447
449
var oldWidth = oldFullLayout . width ,
448
450
oldHeight = oldFullLayout . height ;
449
451
450
- plots . supplyLayoutGlobalDefaults ( newLayout , newFullLayout ) ;
452
+ plots . supplyLayoutGlobalDefaults ( newLayout , newFullLayout , formatObj ) ;
451
453
452
454
if ( ! newLayout . width ) newFullLayout . width = oldWidth ;
453
455
if ( ! newLayout . height ) newFullLayout . height = oldHeight ;
454
456
}
455
457
else {
456
458
457
459
// coerce the updated layout and autosize if needed
458
- plots . supplyLayoutGlobalDefaults ( newLayout , newFullLayout ) ;
460
+ plots . supplyLayoutGlobalDefaults ( newLayout , newFullLayout , formatObj ) ;
459
461
460
462
var missingWidthOrHeight = ( ! newLayout . width || ! newLayout . height ) ,
461
463
autosize = newFullLayout . autosize ,
@@ -472,6 +474,8 @@ plots.supplyDefaults = function(gd) {
472
474
}
473
475
}
474
476
477
+ newFullLayout . _d3locale = getFormatter ( formatObj , newFullLayout . separators ) ;
478
+
475
479
newFullLayout . _initialAutoSizeIsDone = true ;
476
480
477
481
// keep track of how many traces are inputted
@@ -563,6 +567,83 @@ function remapTransformedArrays(cd0, newTrace) {
563
567
}
564
568
}
565
569
570
+ var formatKeys = [
571
+ 'days' , 'shortDays' , 'months' , 'shortMonths' , 'periods' ,
572
+ 'dateTime' , 'date' , 'time' ,
573
+ 'decimal' , 'thousands' , 'grouping' , 'currency'
574
+ ] ;
575
+
576
+ /**
577
+ * getD3FormatObj: use _context to get the d3.locale argument object.
578
+ * decimal and thousands can be overridden later by layout.separators
579
+ * grouping and currency are not presently used by our automatic number
580
+ * formatting system but can be used by custom formats.
581
+ *
582
+ * @returns {object } d3.locale format object
583
+ */
584
+ function getD3FormatObj ( gd ) {
585
+ var locale = gd . _context . locale ;
586
+ if ( ! locale ) locale === 'en-US' ;
587
+
588
+ var formatDone = false ;
589
+ var formatObj = { } ;
590
+
591
+ function includeFormat ( newFormat ) {
592
+ var formatFinished = true ;
593
+ for ( var i = 0 ; i < formatKeys . length ; i ++ ) {
594
+ var formatKey = formatKeys [ i ] ;
595
+ if ( ! formatObj [ formatKey ] ) {
596
+ if ( newFormat [ formatKey ] ) {
597
+ formatObj [ formatKey ] = newFormat [ formatKey ] ;
598
+ }
599
+ else formatFinished = false ;
600
+ }
601
+ }
602
+ if ( formatFinished ) formatDone = true ;
603
+ }
604
+
605
+ // same as localize, look for format parts in each format spec in the chain
606
+ for ( var i = 0 ; i < 2 ; i ++ ) {
607
+ var formats = gd . _context . formats ;
608
+ for ( var j = 0 ; j < 2 ; j ++ ) {
609
+ var formatj = formats [ locale ] ;
610
+ if ( formatj ) {
611
+ includeFormat ( formatj ) ;
612
+ if ( formatDone ) break ;
613
+ }
614
+ formats = Registry . formatRegistry ;
615
+ }
616
+
617
+ var baseLocale = locale . split ( '-' ) [ 0 ] ;
618
+ if ( formatDone || baseLocale === locale ) break ;
619
+ locale = baseLocale ;
620
+ }
621
+
622
+ // lastly pick out defaults from english (non-US, as DMY is so much more common)
623
+ if ( ! formatDone ) includeFormat ( Registry . formatRegistry . en ) ;
624
+
625
+ return formatObj ;
626
+ }
627
+
628
+ /**
629
+ * getFormatter: combine the final separators with the locale formatting object
630
+ * we pulled earlier to generate number and time formatters
631
+ * TODO: remove separators in v2, only use locale, so we don't need this step?
632
+ *
633
+ * @param {object } formatObj: d3.locale format object
634
+ * @param {string } separators: length-2 string to override decimal and thousands
635
+ * separators in number formatting
636
+ *
637
+ * @returns {object } {numberFormat, timeFormat} d3 formatter factory functions
638
+ * for numbers and time
639
+ */
640
+ function getFormatter ( formatObj , separators ) {
641
+ formatObj . decimal = separators . charAt ( 0 ) ;
642
+ formatObj . thousands = separators . charAt ( 1 ) ;
643
+
644
+ return d3 . locale ( formatObj ) ;
645
+ }
646
+
566
647
// Create storage for all of the data related to frames and transitions:
567
648
plots . createTransitionData = function ( gd ) {
568
649
// Set up the default keyframe if it doesn't exist:
@@ -1144,7 +1225,7 @@ function applyTransforms(fullTrace, fullData, layout, fullLayout) {
1144
1225
return dataOut ;
1145
1226
}
1146
1227
1147
- plots . supplyLayoutGlobalDefaults = function ( layoutIn , layoutOut ) {
1228
+ plots . supplyLayoutGlobalDefaults = function ( layoutIn , layoutOut , formatObj ) {
1148
1229
function coerce ( attr , dflt ) {
1149
1230
return Lib . coerce ( layoutIn , layoutOut , plots . layoutAttributes , attr , dflt ) ;
1150
1231
}
@@ -1183,7 +1264,7 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut) {
1183
1264
1184
1265
coerce ( 'paper_bgcolor' ) ;
1185
1266
1186
- coerce ( 'separators' ) ;
1267
+ coerce ( 'separators' , formatObj . decimal + formatObj . thousands ) ;
1187
1268
coerce ( 'hidesources' ) ;
1188
1269
1189
1270
coerce ( 'colorway' ) ;
0 commit comments