toolkit/javascript/d3/src/core/format.js
changeset 47 c0b4a8b5a012
equal deleted inserted replaced
46:efd9c589177a 47:c0b4a8b5a012
       
     1 // TODO align
       
     2 d3.format = function(specifier) {
       
     3   var match = d3_format_re.exec(specifier),
       
     4       fill = match[1] || " ",
       
     5       sign = match[3] || "",
       
     6       zfill = match[5],
       
     7       width = +match[6],
       
     8       comma = match[7],
       
     9       precision = match[8],
       
    10       type = match[9],
       
    11       scale = 1,
       
    12       suffix = "",
       
    13       integer = false;
       
    14 
       
    15   if (precision) precision = +precision.substring(1);
       
    16 
       
    17   if (zfill) {
       
    18     fill = "0"; // TODO align = "=";
       
    19     if (comma) width -= Math.floor((width - 1) / 4);
       
    20   }
       
    21 
       
    22   switch (type) {
       
    23     case "n": comma = true; type = "g"; break;
       
    24     case "%": scale = 100; suffix = "%"; type = "f"; break;
       
    25     case "p": scale = 100; suffix = "%"; type = "r"; break;
       
    26     case "d": integer = true; precision = 0; break;
       
    27     case "s": scale = -1; type = "r"; break;
       
    28   }
       
    29 
       
    30   // If no precision is specified for r, fallback to general notation.
       
    31   if (type == "r" && !precision) type = "g";
       
    32 
       
    33   type = d3_format_types[type] || d3_format_typeDefault;
       
    34 
       
    35   return function(value) {
       
    36 
       
    37     // Return the empty string for floats formatted as ints.
       
    38     if (integer && (value % 1)) return "";
       
    39 
       
    40     // Convert negative to positive, and record the sign prefix.
       
    41     var negative = (value < 0) && (value = -value) ? "\u2212" : sign;
       
    42 
       
    43     // Apply the scale, computing it from the value's exponent for si format.
       
    44     if (scale < 0) {
       
    45       var prefix = d3.formatPrefix(value, precision);
       
    46       value *= prefix.scale;
       
    47       suffix = prefix.symbol;
       
    48     } else {
       
    49       value *= scale;
       
    50     }
       
    51 
       
    52     // Convert to the desired precision.
       
    53     value = type(value, precision);
       
    54 
       
    55     // If the fill character is 0, the sign and group is applied after the fill.
       
    56     if (zfill) {
       
    57       var length = value.length + negative.length;
       
    58       if (length < width) value = new Array(width - length + 1).join(fill) + value;
       
    59       if (comma) value = d3_format_group(value);
       
    60       value = negative + value;
       
    61     }
       
    62 
       
    63     // Otherwise (e.g., space-filling), the sign and group is applied before.
       
    64     else {
       
    65       if (comma) value = d3_format_group(value);
       
    66       value = negative + value;
       
    67       var length = value.length;
       
    68       if (length < width) value = new Array(width - length + 1).join(fill) + value;
       
    69     }
       
    70 
       
    71     return value + suffix;
       
    72   };
       
    73 };
       
    74 
       
    75 // [[fill]align][sign][#][0][width][,][.precision][type]
       
    76 var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/;
       
    77 
       
    78 var d3_format_types = {
       
    79   g: function(x, p) { return x.toPrecision(p); },
       
    80   e: function(x, p) { return x.toExponential(p); },
       
    81   f: function(x, p) { return x.toFixed(p); },
       
    82   r: function(x, p) { return d3.round(x, p = d3_format_precision(x, p)).toFixed(Math.max(0, Math.min(20, p))); }
       
    83 };
       
    84 
       
    85 function d3_format_precision(x, p) {
       
    86   return p - (x ? 1 + Math.floor(Math.log(x + Math.pow(10, 1 + Math.floor(Math.log(x) / Math.LN10) - p)) / Math.LN10) : 1);
       
    87 }
       
    88 
       
    89 function d3_format_typeDefault(x) {
       
    90   return x + "";
       
    91 }
       
    92 
       
    93 // Apply comma grouping for thousands.
       
    94 function d3_format_group(value) {
       
    95   var i = value.lastIndexOf("."),
       
    96       f = i >= 0 ? value.substring(i) : (i = value.length, ""),
       
    97       t = [];
       
    98   while (i > 0) t.push(value.substring(i -= 3, i + 3));
       
    99   return t.reverse().join(",") + f;
       
   100 }