c3-rails 0.4.10 → 0.4.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 24d96a8fc04f0ac3635181db7bbad6b37188e22e
4
- data.tar.gz: 904a53199c8d8d71b11e10b071d3fc10db15285d
3
+ metadata.gz: 90162db1f8f150165ac442b177dc27844ddc85f3
4
+ data.tar.gz: 544bc6b27a93230f0110bf05f9eab6d395e89411
5
5
  SHA512:
6
- metadata.gz: 5ba9d6b81fd23e849392cf3f70caba53bb8384e493d2612d030ac9459cc30a0b5f986ded6f75d9a828fb0a156ec83e62db92c5f555c3ced59bce27207dfea86f
7
- data.tar.gz: dc495fa5f394efba86f1b12d7111f832821b11c7e3570788035d6a9db49387e713b1cdc10b1ddd605fc2496c659bba71a73d8f6a1abdeb64f093bc6b831f0e8f
6
+ metadata.gz: 91430d5a404bb35170b53cf769c84f3f630bfb72ced49842a4f039b03f8b3f7dd80737bab1cd1c000412bff5b9c3d6ad2aa719f25a7393cc389ed3c1bf094cf9
7
+ data.tar.gz: 0c610b66c7606a3c912688ec43c8e3b9f1893e020e92d0eb7beaca5ecf4ad246afe9b607777641ac6feb2d26551c6cd816bb5b79d71827c7d3d58f463876cc1b
data/.gitmodules CHANGED
@@ -1,4 +1,4 @@
1
1
  [submodule "vendor/assets/javascripts/c3"]
2
2
  path = vendor/assets/javascripts/c3
3
- url = git://github.com/masayuki0812/c3.git
3
+ url = git://github.com/c3js/c3.git
4
4
  branch = master
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # c3-rails
2
2
 
3
- [c3](https://github.com/masayuki0812/c3) is a D3-based reusable chart library
3
+ [c3](https://github.com/c3js/c3) is a D3-based reusable chart library
4
4
  that enables deeper integration of charts into web applications.
5
5
 
6
6
  c3-rails provides c3 for Rails 4 (it might work with Rails 3)
@@ -77,6 +77,6 @@ include bootstrap into your project this way..
77
77
 
78
78
  ## License
79
79
 
80
- Both [c3](https://github.com/masayuki0812/c3/blob/master/LICENSE)
80
+ Both [c3](https://github.com/c3js/c3/blob/master/LICENSE)
81
81
  and [c3-rails](https://github.com/SunnyLi/c3-rails/blob/master/LICENSE)
82
82
  are licensed under the MIT license
@@ -1,5 +1,5 @@
1
1
  module C3
2
2
  module Rails
3
- VERSION = "0.4.10"
3
+ VERSION = "0.4.11"
4
4
  end
5
5
  end
@@ -3,7 +3,7 @@
3
3
 
4
4
  /*global define, module, exports, require */
5
5
 
6
- var c3 = { version: "0.4.10" };
6
+ var c3 = { version: "0.4.11" };
7
7
 
8
8
  var c3_chart_fn,
9
9
  c3_chart_internal_fn,
@@ -31,7 +31,10 @@
31
31
  function Chart(config) {
32
32
  var $$ = this.internal = new ChartInternal(this);
33
33
  $$.loadConfig(config);
34
+
35
+ $$.beforeInit(config);
34
36
  $$.init();
37
+ $$.afterInit(config);
35
38
 
36
39
  // bind "this" to nested API
37
40
  (function bindThis(fn, target, argThis) {
@@ -71,13 +74,19 @@
71
74
  c3_chart_internal_fn = c3.chart.internal.fn;
72
75
  c3_chart_internal_axis_fn = c3.chart.internal.axis.fn;
73
76
 
77
+ c3_chart_internal_fn.beforeInit = function () {
78
+ // can do something
79
+ };
80
+ c3_chart_internal_fn.afterInit = function () {
81
+ // can do something
82
+ };
74
83
  c3_chart_internal_fn.init = function () {
75
84
  var $$ = this, config = $$.config;
76
85
 
77
86
  $$.initParams();
78
87
 
79
88
  if (config.data_url) {
80
- $$.convertUrlToData(config.data_url, config.data_mimeType, config.data_keys, $$.initWithData);
89
+ $$.convertUrlToData(config.data_url, config.data_mimeType, config.data_headers, config.data_keys, $$.initWithData);
81
90
  }
82
91
  else if (config.data_json) {
83
92
  $$.initWithData($$.convertJsonToData(config.data_json, config.data_keys));
@@ -248,6 +257,10 @@
248
257
  .on('mouseenter', function () { return config.onmouseover.call($$); })
249
258
  .on('mouseleave', function () { return config.onmouseout.call($$); });
250
259
 
260
+ if ($$.config.svg_classname) {
261
+ $$.svg.attr('class', $$.config.svg_classname);
262
+ }
263
+
251
264
  // Define defs
252
265
  defs = $$.svg.append("defs");
253
266
  $$.clipChart = $$.appendClip(defs, $$.clipId);
@@ -263,6 +276,7 @@
263
276
  if ($$.initSubchart) { $$.initSubchart(); }
264
277
  if ($$.initTooltip) { $$.initTooltip(); }
265
278
  if ($$.initLegend) { $$.initLegend(); }
279
+ if ($$.initTitle) { $$.initTitle(); }
266
280
 
267
281
  /*-- Main Region --*/
268
282
 
@@ -324,20 +338,7 @@
324
338
  }
325
339
 
326
340
  // Bind resize event
327
- if (window.onresize == null) {
328
- window.onresize = $$.generateResize();
329
- }
330
- if (window.onresize.add) {
331
- window.onresize.add(function () {
332
- config.onresize.call($$);
333
- });
334
- window.onresize.add(function () {
335
- $$.api.flush();
336
- });
337
- window.onresize.add(function () {
338
- config.onresized.call($$);
339
- });
340
- }
341
+ $$.bindResize();
341
342
 
342
343
  // export element of the chart
343
344
  $$.api.element = $$.selectChart.node();
@@ -423,7 +424,7 @@
423
424
  // for arc
424
425
  $$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0);
425
426
  $$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10);
426
- if ($$.hasType('gauge')) {
427
+ if ($$.hasType('gauge') && !config.gauge_fullCircle) {
427
428
  $$.arcHeight += $$.height - $$.getGaugeLabelHeight();
428
429
  }
429
430
  if ($$.updateRadius) { $$.updateRadius(); }
@@ -575,9 +576,6 @@
575
576
  $$.subY2.domain($$.getYDomain(targetsToShow, 'y2'));
576
577
  }
577
578
 
578
- // tooltip
579
- $$.tooltip.style("display", "none");
580
-
581
579
  // xgrid focus
582
580
  $$.updateXgridFocus();
583
581
 
@@ -608,6 +606,9 @@
608
606
  $$.updateText(durationForExit);
609
607
  }
610
608
 
609
+ // title
610
+ if ($$.redrawTitle) { $$.redrawTitle(); }
611
+
611
612
  // arc
612
613
  if ($$.redrawArc) { $$.redrawArc(duration, durationForExit, withTransform); }
613
614
 
@@ -914,6 +915,7 @@
914
915
  if (selection.node().parentNode) {
915
916
  window.clearInterval($$.intervalForObserveInserted);
916
917
  $$.updateDimension();
918
+ if ($$.brush) { $$.brush.update(); }
917
919
  $$.config.oninit.call($$);
918
920
  $$.redraw({
919
921
  withTransform: true,
@@ -932,6 +934,49 @@
932
934
  observer.observe(selection.node(), {attributes: true, childList: true, characterData: true});
933
935
  };
934
936
 
937
+ c3_chart_internal_fn.bindResize = function () {
938
+ var $$ = this, config = $$.config;
939
+
940
+ $$.resizeFunction = $$.generateResize();
941
+
942
+ $$.resizeFunction.add(function () {
943
+ config.onresize.call($$);
944
+ });
945
+ if (config.resize_auto) {
946
+ $$.resizeFunction.add(function () {
947
+ if ($$.resizeTimeout !== undefined) {
948
+ window.clearTimeout($$.resizeTimeout);
949
+ }
950
+ $$.resizeTimeout = window.setTimeout(function () {
951
+ delete $$.resizeTimeout;
952
+ $$.api.flush();
953
+ }, 100);
954
+ });
955
+ }
956
+ $$.resizeFunction.add(function () {
957
+ config.onresized.call($$);
958
+ });
959
+
960
+ if (window.attachEvent) {
961
+ window.attachEvent('onresize', $$.resizeFunction);
962
+ } else if (window.addEventListener) {
963
+ window.addEventListener('resize', $$.resizeFunction, false);
964
+ } else {
965
+ // fallback to this, if this is a very old browser
966
+ var wrapper = window.onresize;
967
+ if (!wrapper) {
968
+ // create a wrapper that will call all charts
969
+ wrapper = $$.generateResize();
970
+ } else if (!wrapper.add || !wrapper.remove) {
971
+ // there is already a handler registered, make sure we call it too
972
+ wrapper = $$.generateResize();
973
+ wrapper.add(window.onresize);
974
+ }
975
+ // add this graph to the wrapper, we will be removed if the user calls destroy
976
+ wrapper.add($$.resizeFunction);
977
+ window.onresize = wrapper;
978
+ }
979
+ };
935
980
 
936
981
  c3_chart_internal_fn.generateResize = function () {
937
982
  var resizeFunctions = [];
@@ -943,6 +988,14 @@
943
988
  callResizeFunctions.add = function (f) {
944
989
  resizeFunctions.push(f);
945
990
  };
991
+ callResizeFunctions.remove = function (f) {
992
+ for (var i = 0; i < resizeFunctions.length; i++) {
993
+ if (resizeFunctions[i] === f) {
994
+ resizeFunctions.splice(i, 1);
995
+ break;
996
+ }
997
+ }
998
+ };
946
999
  return callResizeFunctions;
947
1000
  };
948
1001
 
@@ -988,7 +1041,7 @@
988
1041
  parsedDate = date;
989
1042
  } else if (typeof date === 'string') {
990
1043
  parsedDate = $$.dataTimeFormat($$.config.data_xFormat).parse(date);
991
- } else if (typeof date === 'number' || !isNaN(date)) {
1044
+ } else if (typeof date === 'number' && !isNaN(date)) {
992
1045
  parsedDate = new Date(+date);
993
1046
  }
994
1047
  if (!parsedDate || isNaN(+parsedDate)) {
@@ -1015,12 +1068,14 @@
1015
1068
  c3_chart_internal_fn.getDefaultConfig = function () {
1016
1069
  var config = {
1017
1070
  bindto: '#chart',
1071
+ svg_classname: undefined,
1018
1072
  size_width: undefined,
1019
1073
  size_height: undefined,
1020
1074
  padding_left: undefined,
1021
1075
  padding_right: undefined,
1022
1076
  padding_top: undefined,
1023
1077
  padding_bottom: undefined,
1078
+ resize_auto: true,
1024
1079
  zoom_enabled: false,
1025
1080
  zoom_extent: undefined,
1026
1081
  zoom_privileged: false,
@@ -1028,6 +1083,9 @@
1028
1083
  zoom_onzoom: function () {},
1029
1084
  zoom_onzoomstart: function () {},
1030
1085
  zoom_onzoomend: function () {},
1086
+ zoom_x_min: undefined,
1087
+ zoom_x_max: undefined,
1088
+ interaction_brighten: true,
1031
1089
  interaction_enabled: true,
1032
1090
  onmouseover: function () {},
1033
1091
  onmouseout: function () {},
@@ -1066,6 +1124,7 @@
1066
1124
  data_onselected: function () {},
1067
1125
  data_onunselected: function () {},
1068
1126
  data_url: undefined,
1127
+ data_headers: undefined,
1069
1128
  data_json: undefined,
1070
1129
  data_rows: undefined,
1071
1130
  data_columns: undefined,
@@ -1076,6 +1135,7 @@
1076
1135
  // subchart
1077
1136
  subchart_show: false,
1078
1137
  subchart_size_height: 60,
1138
+ subchart_axis_x_show: true,
1079
1139
  subchart_onbrush: function () {},
1080
1140
  // color
1081
1141
  color_pattern: [],
@@ -1092,6 +1152,9 @@
1092
1152
  legend_item_onmouseover: undefined,
1093
1153
  legend_item_onmouseout: undefined,
1094
1154
  legend_equally: false,
1155
+ legend_padding: 0,
1156
+ legend_item_tile_width: 10,
1157
+ legend_item_tile_height: 10,
1095
1158
  // axis
1096
1159
  axis_rotated: false,
1097
1160
  axis_x_show: true,
@@ -1125,7 +1188,8 @@
1125
1188
  axis_y_label: {},
1126
1189
  axis_y_tick_format: undefined,
1127
1190
  axis_y_tick_outer: true,
1128
- axis_y_tick_values: null,
1191
+ axis_y_tick_values: null,
1192
+ axis_y_tick_rotate: 0,
1129
1193
  axis_y_tick_count: undefined,
1130
1194
  axis_y_tick_time_value: undefined,
1131
1195
  axis_y_tick_time_interval: undefined,
@@ -1158,6 +1222,7 @@
1158
1222
  // point - point of each data
1159
1223
  point_show: true,
1160
1224
  point_r: 2.5,
1225
+ point_sensitivity: 10,
1161
1226
  point_focus_expand_enabled: true,
1162
1227
  point_focus_expand_r: undefined,
1163
1228
  point_select_r: undefined,
@@ -1171,26 +1236,36 @@
1171
1236
  bar_zerobased: true,
1172
1237
  // area
1173
1238
  area_zerobased: true,
1239
+ area_above: false,
1174
1240
  // pie
1175
1241
  pie_label_show: true,
1176
1242
  pie_label_format: undefined,
1177
1243
  pie_label_threshold: 0.05,
1178
- pie_expand: true,
1244
+ pie_label_ratio: undefined,
1245
+ pie_expand: {},
1246
+ pie_expand_duration: 50,
1179
1247
  // gauge
1248
+ gauge_fullCircle: false,
1180
1249
  gauge_label_show: true,
1181
1250
  gauge_label_format: undefined,
1182
- gauge_expand: true,
1183
1251
  gauge_min: 0,
1184
1252
  gauge_max: 100,
1253
+ gauge_startingAngle: -1 * Math.PI/2,
1185
1254
  gauge_units: undefined,
1186
1255
  gauge_width: undefined,
1256
+ gauge_expand: {},
1257
+ gauge_expand_duration: 50,
1187
1258
  // donut
1188
1259
  donut_label_show: true,
1189
1260
  donut_label_format: undefined,
1190
1261
  donut_label_threshold: 0.05,
1262
+ donut_label_ratio: undefined,
1191
1263
  donut_width: undefined,
1192
- donut_expand: true,
1193
1264
  donut_title: "",
1265
+ donut_expand: {},
1266
+ donut_expand_duration: 50,
1267
+ // spline
1268
+ spline_interpolation_type: 'cardinal',
1194
1269
  // region - region to change style
1195
1270
  regions: [],
1196
1271
  // tooltip - show when mouseover on each data
@@ -1205,7 +1280,18 @@
1205
1280
  },
1206
1281
  tooltip_init_show: false,
1207
1282
  tooltip_init_x: 0,
1208
- tooltip_init_position: {top: '0px', left: '50px'}
1283
+ tooltip_init_position: {top: '0px', left: '50px'},
1284
+ tooltip_onshow: function () {},
1285
+ tooltip_onhide: function () {},
1286
+ // title
1287
+ title_text: undefined,
1288
+ title_padding: {
1289
+ top: 0,
1290
+ right: 0,
1291
+ bottom: 0,
1292
+ left: 0
1293
+ },
1294
+ title_position: 'top-center',
1209
1295
  };
1210
1296
 
1211
1297
  Object.keys(this.additionalConfig).forEach(function (key) {
@@ -1556,14 +1642,15 @@
1556
1642
  return $$.x.domain();
1557
1643
  };
1558
1644
  c3_chart_internal_fn.trimXDomain = function (domain) {
1559
- var $$ = this;
1560
- if (domain[0] <= $$.orgXDomain[0]) {
1561
- domain[1] = +domain[1] + ($$.orgXDomain[0] - domain[0]);
1562
- domain[0] = $$.orgXDomain[0];
1645
+ var zoomDomain = this.getZoomDomain(),
1646
+ min = zoomDomain[0], max = zoomDomain[1];
1647
+ if (domain[0] <= min) {
1648
+ domain[1] = +domain[1] + (min - domain[0]);
1649
+ domain[0] = min;
1563
1650
  }
1564
- if ($$.orgXDomain[1] <= domain[1]) {
1565
- domain[0] = +domain[0] - (domain[1] - $$.orgXDomain[1]);
1566
- domain[1] = $$.orgXDomain[1];
1651
+ if (max <= domain[1]) {
1652
+ domain[0] = +domain[0] - (domain[1] - max);
1653
+ domain[1] = max;
1567
1654
  }
1568
1655
  return domain;
1569
1656
  };
@@ -1623,7 +1710,7 @@
1623
1710
  var $$ = this, name;
1624
1711
  if (data) {
1625
1712
  name = $$.config.data_names[data.id];
1626
- data.name = name ? name : data.id;
1713
+ data.name = name !== undefined ? name : data.id;
1627
1714
  }
1628
1715
  return data;
1629
1716
  };
@@ -1717,7 +1804,7 @@
1717
1804
  };
1718
1805
  c3_chart_internal_fn.mapToTargetIds = function (ids) {
1719
1806
  var $$ = this;
1720
- return ids ? (isString(ids) ? [ids] : ids) : $$.mapToIds($$.data.targets);
1807
+ return ids ? [].concat(ids) : $$.mapToIds($$.data.targets);
1721
1808
  };
1722
1809
  c3_chart_internal_fn.hasTarget = function (targets, id) {
1723
1810
  var ids = this.mapToIds(targets), i;
@@ -1741,7 +1828,8 @@
1741
1828
  c3_chart_internal_fn.mapTargetsToUniqueXs = function (targets) {
1742
1829
  var $$ = this;
1743
1830
  var xs = $$.d3.set($$.d3.merge(targets.map(function (t) { return t.values.map(function (v) { return +v.x; }); }))).values();
1744
- return $$.isTimeSeries() ? xs.map(function (x) { return new Date(+x); }) : xs.map(function (x) { return +x; });
1831
+ xs = $$.isTimeSeries() ? xs.map(function (x) { return new Date(+x); }) : xs.map(function (x) { return +x; });
1832
+ return xs.sort(function (a, b) { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; });
1745
1833
  };
1746
1834
  c3_chart_internal_fn.addHiddenTargetIds = function (targetIds) {
1747
1835
  this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds);
@@ -1875,7 +1963,7 @@
1875
1963
  return $$.findClosest(candidates, pos);
1876
1964
  };
1877
1965
  c3_chart_internal_fn.findClosest = function (values, pos) {
1878
- var $$ = this, minDist = 100, closest;
1966
+ var $$ = this, minDist = $$.config.point_sensitivity, closest;
1879
1967
 
1880
1968
  // find mouseovering bar
1881
1969
  values.filter(function (v) { return v && $$.isBarType(v.id); }).forEach(function (v) {
@@ -1902,7 +1990,7 @@
1902
1990
  yIndex = config.axis_rotated ? 0 : 1,
1903
1991
  y = $$.circleY(data, data.index),
1904
1992
  x = $$.x(data.x);
1905
- return Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2);
1993
+ return Math.sqrt(Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2));
1906
1994
  };
1907
1995
  c3_chart_internal_fn.convertValuesToStep = function (values) {
1908
1996
  var converted = [].concat(values), i;
@@ -1938,9 +2026,15 @@
1938
2026
  return current;
1939
2027
  };
1940
2028
 
1941
- c3_chart_internal_fn.convertUrlToData = function (url, mimeType, keys, done) {
2029
+ c3_chart_internal_fn.convertUrlToData = function (url, mimeType, headers, keys, done) {
1942
2030
  var $$ = this, type = mimeType ? mimeType : 'csv';
1943
- $$.d3.xhr(url, function (error, data) {
2031
+ var req = $$.d3.xhr(url);
2032
+ if (headers) {
2033
+ Object.keys(headers).forEach(function (header) {
2034
+ req.header(header, headers[header]);
2035
+ });
2036
+ }
2037
+ req.get(function (error, data) {
1944
2038
  var d;
1945
2039
  if (!data) {
1946
2040
  throw new Error(error.responseURL + ' ' + error.status + ' (' + error.statusText + ')');
@@ -1988,7 +2082,10 @@
1988
2082
  var new_row = [];
1989
2083
  targetKeys.forEach(function (key) {
1990
2084
  // convert undefined to null because undefined data will be removed in convertDataToTargets()
1991
- var v = isUndefined(o[key]) ? null : o[key];
2085
+ var v = $$.findValueInJson(o, key);
2086
+ if (isUndefined(v)) {
2087
+ v = null;
2088
+ }
1992
2089
  new_row.push(v);
1993
2090
  });
1994
2091
  new_rows.push(new_row);
@@ -2002,6 +2099,20 @@
2002
2099
  }
2003
2100
  return data;
2004
2101
  };
2102
+ c3_chart_internal_fn.findValueInJson = function (object, path) {
2103
+ path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties (replace [] with .)
2104
+ path = path.replace(/^\./, ''); // strip a leading dot
2105
+ var pathArray = path.split('.');
2106
+ for (var i = 0; i < pathArray.length; ++i) {
2107
+ var k = pathArray[i];
2108
+ if (k in object) {
2109
+ object = object[k];
2110
+ } else {
2111
+ return;
2112
+ }
2113
+ }
2114
+ return object;
2115
+ };
2005
2116
  c3_chart_internal_fn.convertRowsToData = function (rows) {
2006
2117
  var keys = rows[0], new_row = {}, new_rows = [], i, j;
2007
2118
  for (i = 1; i < rows.length; i++) {
@@ -2080,17 +2191,26 @@
2080
2191
  id: convertedId,
2081
2192
  id_org: id,
2082
2193
  values: data.map(function (d, i) {
2083
- var xKey = $$.getXKey(id), rawX = d[xKey], x = $$.generateTargetX(rawX, id, i);
2194
+ var xKey = $$.getXKey(id), rawX = d[xKey],
2195
+ value = d[id] !== null && !isNaN(d[id]) ? +d[id] : null, x;
2084
2196
  // use x as categories if custom x and categorized
2085
- if ($$.isCustomX() && $$.isCategorized() && index === 0 && rawX) {
2086
- if (i === 0) { config.axis_x_categories = []; }
2087
- config.axis_x_categories.push(rawX);
2197
+ if ($$.isCustomX() && $$.isCategorized() && index === 0 && !isUndefined(rawX)) {
2198
+ if (index === 0 && i === 0) {
2199
+ config.axis_x_categories = [];
2200
+ }
2201
+ x = config.axis_x_categories.indexOf(rawX);
2202
+ if (x === -1) {
2203
+ x = config.axis_x_categories.length;
2204
+ config.axis_x_categories.push(rawX);
2205
+ }
2206
+ } else {
2207
+ x = $$.generateTargetX(rawX, id, i);
2088
2208
  }
2089
2209
  // mark as x = undefined if value is undefined and filter to remove after mapped
2090
2210
  if (isUndefined(d[id]) || $$.data.xs[id].length <= i) {
2091
2211
  x = undefined;
2092
2212
  }
2093
- return {x: x, value: d[id] !== null && !isNaN(d[id]) ? +d[id] : null, id: convertedId};
2213
+ return {x: x, value: value, id: convertedId};
2094
2214
  }).filter(function (v) { return isDefined(v.x); })
2095
2215
  };
2096
2216
  });
@@ -2117,6 +2237,10 @@
2117
2237
  });
2118
2238
  });
2119
2239
 
2240
+ // cache information about values
2241
+ $$.hasNegativeValue = $$.hasNegativeValueInTargets(targets);
2242
+ $$.hasPositiveValue = $$.hasPositiveValueInTargets(targets);
2243
+
2120
2244
  // set target types
2121
2245
  if (config.data_type) {
2122
2246
  $$.setTargetType($$.mapToIds(targets).filter(function (id) { return ! (id in config.data_types); }), config.data_type);
@@ -2171,7 +2295,7 @@
2171
2295
  $$.load($$.convertDataToTargets(args.data), args);
2172
2296
  }
2173
2297
  else if (args.url) {
2174
- $$.convertUrlToData(args.url, args.mimeType, args.keys, function (data) {
2298
+ $$.convertUrlToData(args.url, args.mimeType, args.headers, args.keys, function (data) {
2175
2299
  $$.load($$.convertDataToTargets(data), args);
2176
2300
  });
2177
2301
  }
@@ -2514,7 +2638,7 @@
2514
2638
  $$.showXGridFocus(selectedData);
2515
2639
 
2516
2640
  // Show cursor as pointer if point is close to mouse position
2517
- if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < 100) {
2641
+ if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < config.point_sensitivity) {
2518
2642
  $$.svg.select('.' + CLASS.eventRect).style('cursor', 'pointer');
2519
2643
  if (!$$.mouseover) {
2520
2644
  config.data_onmouseover.call($$.api, closest);
@@ -2525,16 +2649,13 @@
2525
2649
  .on('click', function () {
2526
2650
  var targetsToShow = $$.filterTargetsToShow($$.data.targets);
2527
2651
  var mouse, closest;
2528
-
2529
2652
  if ($$.hasArcType(targetsToShow)) { return; }
2530
2653
 
2531
2654
  mouse = d3.mouse(this);
2532
2655
  closest = $$.findClosestFromTargets(targetsToShow, mouse);
2533
-
2534
2656
  if (! closest) { return; }
2535
-
2536
2657
  // select if selection enabled
2537
- if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < 100) {
2658
+ if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < config.point_sensitivity) {
2538
2659
  $$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(closest.id)).selectAll('.' + CLASS.shape + '-' + closest.index).each(function () {
2539
2660
  if (config.data_selection_grouped || $$.isWithinShape(this, closest)) {
2540
2661
  $$.toggleShape(this, closest, closest.index);
@@ -2573,11 +2694,16 @@
2573
2694
  c3_chart_internal_fn.getCurrentHeight = function () {
2574
2695
  var $$ = this, config = $$.config,
2575
2696
  h = config.size_height ? config.size_height : $$.getParentHeight();
2576
- return h > 0 ? h : 320 / ($$.hasType('gauge') ? 2 : 1);
2697
+ return h > 0 ? h : 320 / ($$.hasType('gauge') && !config.gauge_fullCircle ? 2 : 1);
2577
2698
  };
2578
2699
  c3_chart_internal_fn.getCurrentPaddingTop = function () {
2579
- var config = this.config;
2580
- return isValue(config.padding_top) ? config.padding_top : 0;
2700
+ var $$ = this,
2701
+ config = $$.config,
2702
+ padding = isValue(config.padding_top) ? config.padding_top : 0;
2703
+ if ($$.title && $$.title.node()) {
2704
+ padding += $$.getTitlePadding();
2705
+ }
2706
+ return padding;
2581
2707
  };
2582
2708
  c3_chart_internal_fn.getCurrentPaddingBottom = function () {
2583
2709
  var config = this.config;
@@ -2658,12 +2784,18 @@
2658
2784
  var $$ = this, config = $$.config, h = 30;
2659
2785
  if (axisId === 'x' && !config.axis_x_show) { return 8; }
2660
2786
  if (axisId === 'x' && config.axis_x_height) { return config.axis_x_height; }
2661
- if (axisId === 'y' && !config.axis_y_show) { return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1; }
2787
+ if (axisId === 'y' && !config.axis_y_show) {
2788
+ return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1;
2789
+ }
2662
2790
  if (axisId === 'y2' && !config.axis_y2_show) { return $$.rotated_padding_top; }
2663
2791
  // Calculate x axis height when tick rotated
2664
2792
  if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) {
2665
2793
  h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_x_tick_rotate) / 180);
2666
2794
  }
2795
+ // Calculate y axis height when tick rotated
2796
+ if (axisId === 'y' && config.axis_rotated && config.axis_y_tick_rotate) {
2797
+ h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_y_tick_rotate) / 180);
2798
+ }
2667
2799
  return h + ($$.axis.getLabelPositionById(axisId).isInner ? 0 : 10) + (axisId === 'y2' ? -10 : 0);
2668
2800
  };
2669
2801
 
@@ -2714,7 +2846,17 @@
2714
2846
  var values = $$.isStepType(d) ? $$.convertValuesToStep(t.values) : t.values;
2715
2847
  if (t.id === d.id || indices[t.id] !== indices[d.id]) { return; }
2716
2848
  if (targetIds.indexOf(t.id) < targetIds.indexOf(d.id)) {
2717
- if (values[i].value * d.value >= 0) {
2849
+ // check if the x values line up
2850
+ if (typeof values[i] === 'undefined' || +values[i].x !== +d.x) { // "+" for timeseries
2851
+ // if not, try to find the value that does line up
2852
+ i = -1;
2853
+ values.forEach(function (v, j) {
2854
+ if (v.x === d.x) {
2855
+ i = j;
2856
+ }
2857
+ });
2858
+ }
2859
+ if (i in values && values[i].value * d.value >= 0) {
2718
2860
  offset += scale(values[i].value) - y0;
2719
2861
  }
2720
2862
  }
@@ -2739,8 +2881,9 @@
2739
2881
 
2740
2882
 
2741
2883
  c3_chart_internal_fn.getInterpolate = function (d) {
2742
- var $$ = this;
2743
- return $$.isSplineType(d) ? "cardinal" : $$.isStepType(d) ? $$.config.line_step_type : "linear";
2884
+ var $$ = this,
2885
+ interpolation = $$.isInterpolationType($$.config.spline_interpolation_type) ? $$.config.spline_interpolation_type : 'cardinal';
2886
+ return $$.isSplineType(d) ? interpolation : $$.isStepType(d) ? $$.config.line_step_type : "linear";
2744
2887
  };
2745
2888
 
2746
2889
  c3_chart_internal_fn.initLine = function () {
@@ -2801,7 +2944,7 @@
2801
2944
  };
2802
2945
  c3_chart_internal_fn.redrawLine = function (drawLine, withTransition) {
2803
2946
  return [
2804
- (withTransition ? this.mainLine.transition() : this.mainLine)
2947
+ (withTransition ? this.mainLine.transition(Math.random().toString()) : this.mainLine)
2805
2948
  .attr("d", drawLine)
2806
2949
  .style("stroke", this.color)
2807
2950
  .style("opacity", 1)
@@ -2977,7 +3120,7 @@
2977
3120
  };
2978
3121
  c3_chart_internal_fn.redrawArea = function (drawArea, withTransition) {
2979
3122
  return [
2980
- (withTransition ? this.mainArea.transition() : this.mainArea)
3123
+ (withTransition ? this.mainArea.transition(Math.random().toString()) : this.mainArea)
2981
3124
  .attr("d", drawArea)
2982
3125
  .style("fill", this.color)
2983
3126
  .style("opacity", this.orgAreaOpacity)
@@ -2995,7 +3138,7 @@
2995
3138
  return config.data_groups.length > 0 ? getPoints(d, i)[1][1] : yScaleGetter.call($$, d.id)(d.value);
2996
3139
  };
2997
3140
 
2998
- area = config.axis_rotated ? area.x0(value0).x1(value1).y(xValue) : area.x(xValue).y0(value0).y1(value1);
3141
+ area = config.axis_rotated ? area.x0(value0).x1(value1).y(xValue) : area.x(xValue).y0(config.area_above ? 0 : value0).y1(value1);
2999
3142
  if (!config.line_connectNull) {
3000
3143
  area = area.defined(function (d) { return d.value !== null; });
3001
3144
  }
@@ -3060,12 +3203,12 @@
3060
3203
  c3_chart_internal_fn.redrawCircle = function (cx, cy, withTransition) {
3061
3204
  var selectedCircles = this.main.selectAll('.' + CLASS.selectedCircle);
3062
3205
  return [
3063
- (withTransition ? this.mainCircle.transition() : this.mainCircle)
3206
+ (withTransition ? this.mainCircle.transition(Math.random().toString()) : this.mainCircle)
3064
3207
  .style('opacity', this.opacityForCircle.bind(this))
3065
3208
  .style("fill", this.color)
3066
3209
  .attr("cx", cx)
3067
3210
  .attr("cy", cy),
3068
- (withTransition ? selectedCircles.transition() : selectedCircles)
3211
+ (withTransition ? selectedCircles.transition(Math.random().toString()) : selectedCircles)
3069
3212
  .attr("cx", cx)
3070
3213
  .attr("cy", cy)
3071
3214
  ];
@@ -3117,7 +3260,7 @@
3117
3260
  };
3118
3261
  c3_chart_internal_fn.pointSelectR = function (d) {
3119
3262
  var $$ = this, config = $$.config;
3120
- return config.point_select_r ? config.point_select_r : $$.pointR(d) * 4;
3263
+ return isFunction(config.point_select_r) ? config.point_select_r(d) : ((config.point_select_r) ? config.point_select_r : $$.pointR(d) * 4);
3121
3264
  };
3122
3265
  c3_chart_internal_fn.isWithinCircle = function (that, r) {
3123
3266
  var d3 = this.d3,
@@ -3173,7 +3316,7 @@
3173
3316
  };
3174
3317
  c3_chart_internal_fn.redrawBar = function (drawBar, withTransition) {
3175
3318
  return [
3176
- (withTransition ? this.mainBar.transition() : this.mainBar)
3319
+ (withTransition ? this.mainBar.transition(Math.random().toString()) : this.mainBar)
3177
3320
  .attr('d', drawBar)
3178
3321
  .style("fill", this.color)
3179
3322
  .style("opacity", 1)
@@ -3301,14 +3444,16 @@
3301
3444
  .style("fill-opacity", forFlow ? 0 : this.opacityForText.bind(this))
3302
3445
  ];
3303
3446
  };
3304
- c3_chart_internal_fn.getTextRect = function (text, cls) {
3447
+ c3_chart_internal_fn.getTextRect = function (text, cls, element) {
3305
3448
  var dummy = this.d3.select('body').append('div').classed('c3', true),
3306
3449
  svg = dummy.append("svg").style('visibility', 'hidden').style('position', 'fixed').style('top', 0).style('left', 0),
3450
+ font = this.d3.select(element).style('font'),
3307
3451
  rect;
3308
3452
  svg.selectAll('.dummy')
3309
3453
  .data([text])
3310
3454
  .enter().append('text')
3311
3455
  .classed(cls ? cls : "", true)
3456
+ .style('font', font)
3312
3457
  .text(text)
3313
3458
  .each(function () { rect = this.getBoundingClientRect(); });
3314
3459
  dummy.remove();
@@ -3352,7 +3497,7 @@
3352
3497
  yPos = (points[0][0] + points[2][0] + box.height * 0.6) / 2;
3353
3498
  } else {
3354
3499
  yPos = points[2][1];
3355
- if (d.value < 0) {
3500
+ if (d.value < 0 || (d.value === 0 && !$$.hasPositiveValue)) {
3356
3501
  yPos += box.height;
3357
3502
  if ($$.isBarType(d) && $$.isSafari()) {
3358
3503
  yPos -= 3;
@@ -3466,6 +3611,9 @@
3466
3611
  c3_chart_internal_fn.barOrLineData = function (d) {
3467
3612
  return this.isBarType(d) || this.isLineType(d) ? d.values : [];
3468
3613
  };
3614
+ c3_chart_internal_fn.isInterpolationType = function (type) {
3615
+ return ['linear', 'linear-closed', 'basis', 'basis-open', 'basis-closed', 'bundle', 'cardinal', 'cardinal-open', 'cardinal-closed', 'monotone'].indexOf(type) >= 0;
3616
+ };
3469
3617
 
3470
3618
  c3_chart_internal_fn.initGrid = function () {
3471
3619
  var $$ = this, config = $$.config, d3 = $$.d3;
@@ -3739,21 +3887,44 @@
3739
3887
  titleFormat = config.tooltip_format_title || defaultTitleFormat,
3740
3888
  nameFormat = config.tooltip_format_name || function (name) { return name; },
3741
3889
  valueFormat = config.tooltip_format_value || defaultValueFormat,
3742
- text, i, title, value, name, bgcolor;
3890
+ text, i, title, value, name, bgcolor,
3891
+ orderAsc = $$.isOrderAsc();
3892
+
3893
+ if (config.data_groups.length === 0) {
3894
+ d.sort(function(a, b){
3895
+ var v1 = a ? a.value : null, v2 = b ? b.value : null;
3896
+ return orderAsc ? v1 - v2 : v2 - v1;
3897
+ });
3898
+ } else {
3899
+ var ids = $$.orderTargets($$.data.targets).map(function (i) {
3900
+ return i.id;
3901
+ });
3902
+ d.sort(function(a, b) {
3903
+ var v1 = a ? a.value : null, v2 = b ? b.value : null;
3904
+ if (v1 > 0 && v2 > 0) {
3905
+ v1 = a ? ids.indexOf(a.id) : null;
3906
+ v2 = b ? ids.indexOf(b.id) : null;
3907
+ }
3908
+ return orderAsc ? v1 - v2 : v2 - v1;
3909
+ });
3910
+ }
3911
+
3743
3912
  for (i = 0; i < d.length; i++) {
3744
3913
  if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; }
3745
3914
 
3746
3915
  if (! text) {
3747
- title = titleFormat ? titleFormat(d[i].x) : d[i].x;
3748
- text = "<table class='" + CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
3916
+ title = sanitise(titleFormat ? titleFormat(d[i].x) : d[i].x);
3917
+ text = "<table class='" + $$.CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
3749
3918
  }
3750
3919
 
3751
- value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index);
3920
+ value = sanitise(valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index, d));
3752
3921
  if (value !== undefined) {
3753
- name = nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index);
3922
+ // Skip elements when their name is set to null
3923
+ if (d[i].name === null) { continue; }
3924
+ name = sanitise(nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index));
3754
3925
  bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
3755
3926
 
3756
- text += "<tr class='" + CLASS.tooltipName + "-" + d[i].id + "'>";
3927
+ text += "<tr class='" + $$.CLASS.tooltipName + "-" + $$.getTargetSelectorSuffix(d[i].id) + "'>";
3757
3928
  text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
3758
3929
  text += "<td class='value'>" + value + "</td>";
3759
3930
  text += "</tr>";
@@ -3785,7 +3956,7 @@
3785
3956
  }
3786
3957
 
3787
3958
  if (tooltipRight > chartRight) {
3788
- // 20 is needed for Firefox to keep tooletip width
3959
+ // 20 is needed for Firefox to keep tooltip width
3789
3960
  tooltipLeft -= tooltipRight - chartRight + 20;
3790
3961
  }
3791
3962
  if (tooltipTop + tHeight > $$.currentHeight) {
@@ -3937,19 +4108,24 @@
3937
4108
  };
3938
4109
  c3_chart_internal_fn.updateLegend = function (targetIds, options, transitions) {
3939
4110
  var $$ = this, config = $$.config;
3940
- var xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect;
3941
- var paddingTop = 4, paddingRight = 10, maxWidth = 0, maxHeight = 0, posMin = 10, tileWidth = 15;
4111
+ var xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect, x1ForLegendTile, x2ForLegendTile, yForLegendTile;
4112
+ var paddingTop = 4, paddingRight = 10, maxWidth = 0, maxHeight = 0, posMin = 10, tileWidth = config.legend_item_tile_width + 5;
3942
4113
  var l, totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = [0], steps = {}, step = 0;
3943
4114
  var withTransition, withTransitionForTransform;
3944
4115
  var texts, rects, tiles, background;
3945
4116
 
4117
+ // Skip elements when their name is set to null
4118
+ targetIds = targetIds.filter(function(id) {
4119
+ return !isDefined(config.data_names[id]) || config.data_names[id] !== null;
4120
+ });
4121
+
3946
4122
  options = options || {};
3947
4123
  withTransition = getOption(options, "withTransition", true);
3948
4124
  withTransitionForTransform = getOption(options, "withTransitionForTransform", true);
3949
4125
 
3950
4126
  function getTextBox(textElement, id) {
3951
4127
  if (!$$.legendItemTextBox[id]) {
3952
- $$.legendItemTextBox[id] = $$.getTextRect(textElement.textContent, CLASS.legendItem);
4128
+ $$.legendItemTextBox[id] = $$.getTextRect(textElement.textContent, CLASS.legendItem, textElement);
3953
4129
  }
3954
4130
  return $$.legendItemTextBox[id];
3955
4131
  }
@@ -3957,7 +4133,7 @@
3957
4133
  function updatePositions(textElement, id, index) {
3958
4134
  var reset = index === 0, isLast = index === targetIds.length - 1,
3959
4135
  box = getTextBox(textElement, id),
3960
- itemWidth = box.width + tileWidth + (isLast && !($$.isLegendRight || $$.isLegendInset) ? 0 : paddingRight),
4136
+ itemWidth = box.width + tileWidth + (isLast && !($$.isLegendRight || $$.isLegendInset) ? 0 : paddingRight) + config.legend_padding,
3961
4137
  itemHeight = box.height + paddingTop,
3962
4138
  itemLength = $$.isLegendRight || $$.isLegendInset ? itemHeight : itemWidth,
3963
4139
  areaLength = $$.isLegendRight || $$.isLegendInset ? $$.getLegendHeight() : $$.getLegendWidth(),
@@ -4030,10 +4206,13 @@
4030
4206
  xForLegend = function (id) { return margins[steps[id]] + offsets[id]; };
4031
4207
  yForLegend = function (id) { return maxHeight * steps[id]; };
4032
4208
  }
4033
- xForLegendText = function (id, i) { return xForLegend(id, i) + 14; };
4209
+ xForLegendText = function (id, i) { return xForLegend(id, i) + 4 + config.legend_item_tile_width; };
4034
4210
  yForLegendText = function (id, i) { return yForLegend(id, i) + 9; };
4035
4211
  xForLegendRect = function (id, i) { return xForLegend(id, i); };
4036
4212
  yForLegendRect = function (id, i) { return yForLegend(id, i) - 5; };
4213
+ x1ForLegendTile = function (id, i) { return xForLegend(id, i) - 2; };
4214
+ x2ForLegendTile = function (id, i) { return xForLegend(id, i) - 2 + config.legend_item_tile_width; };
4215
+ yForLegendTile = function (id, i) { return yForLegend(id, i) + 4; };
4037
4216
 
4038
4217
  // Define g for legend area
4039
4218
  l = $$.legend.selectAll('.' + CLASS.legendItem)
@@ -4056,20 +4235,24 @@
4056
4235
  }
4057
4236
  })
4058
4237
  .on('mouseover', function (id) {
4059
- $$.d3.select(this).classed(CLASS.legendItemFocused, true);
4060
- if (!$$.transiting && $$.isTargetToShow(id)) {
4061
- $$.api.focus(id);
4062
- }
4063
4238
  if (config.legend_item_onmouseover) {
4064
4239
  config.legend_item_onmouseover.call($$, id);
4065
4240
  }
4241
+ else {
4242
+ $$.d3.select(this).classed(CLASS.legendItemFocused, true);
4243
+ if (!$$.transiting && $$.isTargetToShow(id)) {
4244
+ $$.api.focus(id);
4245
+ }
4246
+ }
4066
4247
  })
4067
4248
  .on('mouseout', function (id) {
4068
- $$.d3.select(this).classed(CLASS.legendItemFocused, false);
4069
- $$.api.revert();
4070
4249
  if (config.legend_item_onmouseout) {
4071
4250
  config.legend_item_onmouseout.call($$, id);
4072
4251
  }
4252
+ else {
4253
+ $$.d3.select(this).classed(CLASS.legendItemFocused, false);
4254
+ $$.api.revert();
4255
+ }
4073
4256
  });
4074
4257
  l.append('text')
4075
4258
  .text(function (id) { return isDefined(config.data_names[id]) ? config.data_names[id] : id; })
@@ -4082,14 +4265,15 @@
4082
4265
  .style('fill-opacity', 0)
4083
4266
  .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendRect : -200)
4084
4267
  .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendRect);
4085
- l.append('rect')
4086
- .attr("class", CLASS.legendItemTile)
4268
+ l.append('line')
4269
+ .attr('class', CLASS.legendItemTile)
4270
+ .style('stroke', $$.color)
4087
4271
  .style("pointer-events", "none")
4088
- .style('fill', $$.color)
4089
- .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200)
4090
- .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegend)
4091
- .attr('width', 10)
4092
- .attr('height', 10);
4272
+ .attr('x1', $$.isLegendRight || $$.isLegendInset ? x1ForLegendTile : -200)
4273
+ .attr('y1', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile)
4274
+ .attr('x2', $$.isLegendRight || $$.isLegendInset ? x2ForLegendTile : -200)
4275
+ .attr('y2', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile)
4276
+ .attr('stroke-width', config.legend_item_tile_height);
4093
4277
 
4094
4278
  // Set background for inset legend
4095
4279
  background = $$.legend.select('.' + CLASS.legendBackground + ' rect');
@@ -4115,12 +4299,14 @@
4115
4299
  .attr('x', xForLegendRect)
4116
4300
  .attr('y', yForLegendRect);
4117
4301
 
4118
- tiles = $$.legend.selectAll('rect.' + CLASS.legendItemTile)
4119
- .data(targetIds);
4120
- (withTransition ? tiles.transition() : tiles)
4121
- .style('fill', $$.color)
4122
- .attr('x', xForLegend)
4123
- .attr('y', yForLegend);
4302
+ tiles = $$.legend.selectAll('line.' + CLASS.legendItemTile)
4303
+ .data(targetIds);
4304
+ (withTransition ? tiles.transition() : tiles)
4305
+ .style('stroke', $$.color)
4306
+ .attr('x1', x1ForLegendTile)
4307
+ .attr('y1', yForLegendTile)
4308
+ .attr('x2', x2ForLegendTile)
4309
+ .attr('y2', yForLegendTile);
4124
4310
 
4125
4311
  if (background) {
4126
4312
  (withTransition ? background.transition() : background)
@@ -4145,6 +4331,38 @@
4145
4331
  $$.legendHasRendered = true;
4146
4332
  };
4147
4333
 
4334
+ c3_chart_internal_fn.initTitle = function () {
4335
+ var $$ = this;
4336
+ $$.title = $$.svg.append("text")
4337
+ .text($$.config.title_text)
4338
+ .attr("class", $$.CLASS.title);
4339
+ };
4340
+ c3_chart_internal_fn.redrawTitle = function () {
4341
+ var $$ = this;
4342
+ $$.title
4343
+ .attr("x", $$.xForTitle.bind($$))
4344
+ .attr("y", $$.yForTitle.bind($$));
4345
+ };
4346
+ c3_chart_internal_fn.xForTitle = function () {
4347
+ var $$ = this, config = $$.config, position = config.title_position || 'left', x;
4348
+ if (position.indexOf('right') >= 0) {
4349
+ x = $$.currentWidth - $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width - config.title_padding.right;
4350
+ } else if (position.indexOf('center') >= 0) {
4351
+ x = ($$.currentWidth - $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width) / 2;
4352
+ } else { // left
4353
+ x = config.title_padding.left;
4354
+ }
4355
+ return x;
4356
+ };
4357
+ c3_chart_internal_fn.yForTitle = function () {
4358
+ var $$ = this;
4359
+ return $$.config.title_padding.top + $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).height;
4360
+ };
4361
+ c3_chart_internal_fn.getTitlePadding = function() {
4362
+ var $$ = this;
4363
+ return $$.yForTitle() + $$.config.title_padding.bottom;
4364
+ };
4365
+
4148
4366
  function Axis(owner) {
4149
4367
  API.call(this, owner);
4150
4368
  }
@@ -4195,7 +4413,7 @@
4195
4413
  },
4196
4414
  axis = c3_axis($$.d3, axisParams).scale(scale).orient(orient);
4197
4415
 
4198
- if ($$.isTimeSeries() && tickValues) {
4416
+ if ($$.isTimeSeries() && tickValues && typeof tickValues !== "function") {
4199
4417
  tickValues = tickValues.map(function (v) { return $$.parseDate(v); });
4200
4418
  }
4201
4419
 
@@ -4223,17 +4441,16 @@
4223
4441
  }
4224
4442
  return tickValues;
4225
4443
  };
4226
- Axis.prototype.getYAxis = function getYAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition) {
4227
- var axisParams = {
4228
- withOuterTick: withOuterTick,
4229
- withoutTransition: withoutTransition,
4230
- },
4231
- $$ = this.owner,
4232
- d3 = $$.d3,
4233
- config = $$.config,
4234
- axis = c3_axis(d3, axisParams).scale(scale).orient(orient).tickFormat(tickFormat);
4444
+ Axis.prototype.getYAxis = function getYAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) {
4445
+ var $$ = this.owner, config = $$.config,
4446
+ axisParams = {
4447
+ withOuterTick: withOuterTick,
4448
+ withoutTransition: withoutTransition,
4449
+ tickTextRotate: withoutRotateTickText ? 0 : config.axis_y_tick_rotate
4450
+ },
4451
+ axis = c3_axis($$.d3, axisParams).scale(scale).orient(orient).tickFormat(tickFormat);
4235
4452
  if ($$.isTimeSeriesY()) {
4236
- axis.ticks(d3.time[config.axis_y_tick_time_value], config.axis_y_tick_time_interval);
4453
+ axis.ticks($$.d3.time[config.axis_y_tick_time_value], config.axis_y_tick_time_interval);
4237
4454
  } else {
4238
4455
  axis.tickValues(tickValues);
4239
4456
  }
@@ -4423,10 +4640,10 @@
4423
4640
  targetsToShow = $$.filterTargetsToShow($$.data.targets);
4424
4641
  if (id === 'y') {
4425
4642
  scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y'));
4426
- axis = this.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, false, true);
4643
+ axis = this.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, false, true, true);
4427
4644
  } else if (id === 'y2') {
4428
4645
  scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2'));
4429
- axis = this.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, false, true);
4646
+ axis = this.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, false, true, true);
4430
4647
  } else {
4431
4648
  scale = $$.x.copy().domain($$.getXDomain(targetsToShow));
4432
4649
  axis = this.getXAxis(scale, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, false, true, true);
@@ -4468,14 +4685,15 @@
4468
4685
  .text(this.textForY2AxisLabel.bind(this));
4469
4686
  };
4470
4687
  Axis.prototype.getPadding = function getPadding(padding, key, defaultValue, domainLength) {
4471
- if (!isValue(padding[key])) {
4688
+ var p = typeof padding === 'number' ? padding : padding[key];
4689
+ if (!isValue(p)) {
4472
4690
  return defaultValue;
4473
4691
  }
4474
4692
  if (padding.unit === 'ratio') {
4475
4693
  return padding[key] * domainLength;
4476
4694
  }
4477
4695
  // assume padding is pixels if unit is not specified
4478
- return this.convertPixelsToAxisPadding(padding[key], domainLength);
4696
+ return this.convertPixelsToAxisPadding(p, domainLength);
4479
4697
  };
4480
4698
  Axis.prototype.convertPixelsToAxisPadding = function convertPixelsToAxisPadding(pixels, domainLength) {
4481
4699
  var $$ = this.owner,
@@ -4617,7 +4835,12 @@
4617
4835
  c3_chart_internal_fn.updateAngle = function (d) {
4618
4836
  var $$ = this, config = $$.config,
4619
4837
  found = false, index = 0,
4620
- gMin = config.gauge_min, gMax = config.gauge_max, gTic, gValue;
4838
+ gMin, gMax, gTic, gValue;
4839
+
4840
+ if (!config) {
4841
+ return null;
4842
+ }
4843
+
4621
4844
  $$.pie($$.filterTargetsToShow($$.data.targets)).forEach(function (t) {
4622
4845
  if (! found && t.data.id === d.data.id) {
4623
4846
  found = true;
@@ -4633,9 +4856,11 @@
4633
4856
  d.endAngle = d.startAngle;
4634
4857
  }
4635
4858
  if ($$.isGaugeType(d.data)) {
4636
- gTic = (Math.PI) / (gMax - gMin);
4859
+ gMin = config.gauge_min;
4860
+ gMax = config.gauge_max;
4861
+ gTic = (Math.PI * (config.gauge_fullCircle ? 2 : 1)) / (gMax - gMin);
4637
4862
  gValue = d.value < gMin ? 0 : d.value < gMax ? d.value - gMin : (gMax - gMin);
4638
- d.startAngle = -1 * (Math.PI / 2);
4863
+ d.startAngle = config.gauge_startingAngle;
4639
4864
  d.endAngle = d.startAngle + gTic * gValue;
4640
4865
  }
4641
4866
  return found ? d : null;
@@ -4670,15 +4895,20 @@
4670
4895
 
4671
4896
 
4672
4897
  c3_chart_internal_fn.transformForArcLabel = function (d) {
4673
- var $$ = this,
4898
+ var $$ = this, config = $$.config,
4674
4899
  updated = $$.updateAngle(d), c, x, y, h, ratio, translate = "";
4675
4900
  if (updated && !$$.hasType('gauge')) {
4676
4901
  c = this.svgArc.centroid(updated);
4677
4902
  x = isNaN(c[0]) ? 0 : c[0];
4678
4903
  y = isNaN(c[1]) ? 0 : c[1];
4679
4904
  h = Math.sqrt(x * x + y * y);
4680
- // TODO: ratio should be an option?
4681
- ratio = $$.radius && h ? (36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) * $$.radius / h : 0;
4905
+ if ($$.hasType('donut') && config.donut_label_ratio) {
4906
+ ratio = isFunction(config.donut_label_ratio) ? config.donut_label_ratio(d, $$.radius, h) : config.donut_label_ratio;
4907
+ } else if ($$.hasType('pie') && config.pie_label_ratio) {
4908
+ ratio = isFunction(config.pie_label_ratio) ? config.pie_label_ratio(d, $$.radius, h) : config.pie_label_ratio;
4909
+ } else {
4910
+ ratio = $$.radius && h ? (36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) * $$.radius / h : 0;
4911
+ }
4682
4912
  translate = "translate(" + (x * ratio) + ',' + (y * ratio) + ")";
4683
4913
  }
4684
4914
  return translate;
@@ -4686,7 +4916,8 @@
4686
4916
 
4687
4917
  c3_chart_internal_fn.getArcRatio = function (d) {
4688
4918
  var $$ = this,
4689
- whole = $$.hasType('gauge') ? Math.PI : (Math.PI * 2);
4919
+ config = $$.config,
4920
+ whole = Math.PI * ($$.hasType('gauge') && !config.gauge_fullCircle ? 1 : 2);
4690
4921
  return d ? (d.endAngle - d.startAngle) / whole : null;
4691
4922
  };
4692
4923
 
@@ -4733,9 +4964,9 @@
4733
4964
  $$.svg.selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc)).each(function (d) {
4734
4965
  if (! $$.shouldExpand(d.data.id)) { return; }
4735
4966
  $$.d3.select(this).selectAll('path')
4736
- .transition().duration(50)
4967
+ .transition().duration($$.expandDuration(d.data.id))
4737
4968
  .attr("d", $$.svgArcExpanded)
4738
- .transition().duration(100)
4969
+ .transition().duration($$.expandDuration(d.data.id) * 2)
4739
4970
  .attr("d", $$.svgArcExpandedSub)
4740
4971
  .each(function (d) {
4741
4972
  if ($$.isDonutType(d.data)) {
@@ -4753,15 +4984,34 @@
4753
4984
  targetIds = $$.mapToTargetIds(targetIds);
4754
4985
 
4755
4986
  $$.svg.selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc)).selectAll('path')
4756
- .transition().duration(50)
4987
+ .transition().duration(function(d) {
4988
+ return $$.expandDuration(d.data.id);
4989
+ })
4757
4990
  .attr("d", $$.svgArc);
4758
4991
  $$.svg.selectAll('.' + CLASS.arc)
4759
4992
  .style("opacity", 1);
4760
4993
  };
4761
4994
 
4995
+ c3_chart_internal_fn.expandDuration = function (id) {
4996
+ var $$ = this, config = $$.config;
4997
+
4998
+ if ($$.isDonutType(id)) {
4999
+ return config.donut_expand_duration;
5000
+ } else if ($$.isGaugeType(id)) {
5001
+ return config.gauge_expand_duration;
5002
+ } else if ($$.isPieType(id)) {
5003
+ return config.pie_expand_duration;
5004
+ } else {
5005
+ return 50;
5006
+ }
5007
+
5008
+ };
5009
+
4762
5010
  c3_chart_internal_fn.shouldExpand = function (id) {
4763
5011
  var $$ = this, config = $$.config;
4764
- return ($$.isDonutType(id) && config.donut_expand) || ($$.isGaugeType(id) && config.gauge_expand) || ($$.isPieType(id) && config.pie_expand);
5012
+ return ($$.isDonutType(id) && config.donut_expand) ||
5013
+ ($$.isGaugeType(id) && config.gauge_expand) ||
5014
+ ($$.isPieType(id) && config.pie_expand);
4765
5015
  };
4766
5016
 
4767
5017
  c3_chart_internal_fn.shouldShowArcLabel = function () {
@@ -4842,7 +5092,7 @@
4842
5092
  .style("opacity", 0)
4843
5093
  .each(function (d) {
4844
5094
  if ($$.isGaugeType(d.data)) {
4845
- d.startAngle = d.endAngle = -1 * (Math.PI / 2);
5095
+ d.startAngle = d.endAngle = config.gauge_startingAngle;
4846
5096
  }
4847
5097
  this._current = d;
4848
5098
  });
@@ -4855,18 +5105,22 @@
4855
5105
  return;
4856
5106
  }
4857
5107
  updated = $$.updateAngle(d);
4858
- arcData = $$.convertToArcData(updated);
4859
- // transitions
4860
- $$.expandArc(updated.data.id);
4861
- $$.api.focus(updated.data.id);
4862
- $$.toggleFocusLegend(updated.data.id, true);
4863
- $$.config.data_onmouseover(arcData, this);
5108
+ if (updated) {
5109
+ arcData = $$.convertToArcData(updated);
5110
+ // transitions
5111
+ $$.expandArc(updated.data.id);
5112
+ $$.api.focus(updated.data.id);
5113
+ $$.toggleFocusLegend(updated.data.id, true);
5114
+ $$.config.data_onmouseover(arcData, this);
5115
+ }
4864
5116
  } : null)
4865
5117
  .on('mousemove', config.interaction_enabled ? function (d) {
4866
- var updated = $$.updateAngle(d),
5118
+ var updated = $$.updateAngle(d), arcData, selectedData;
5119
+ if (updated) {
4867
5120
  arcData = $$.convertToArcData(updated),
4868
5121
  selectedData = [arcData];
4869
- $$.showTooltip(selectedData, this);
5122
+ $$.showTooltip(selectedData, this);
5123
+ }
4870
5124
  } : null)
4871
5125
  .on('mouseout', config.interaction_enabled ? function (d) {
4872
5126
  var updated, arcData;
@@ -4874,19 +5128,25 @@
4874
5128
  return;
4875
5129
  }
4876
5130
  updated = $$.updateAngle(d);
4877
- arcData = $$.convertToArcData(updated);
4878
- // transitions
4879
- $$.unexpandArc(updated.data.id);
4880
- $$.api.revert();
4881
- $$.revertLegend();
4882
- $$.hideTooltip();
4883
- $$.config.data_onmouseout(arcData, this);
5131
+ if (updated) {
5132
+ arcData = $$.convertToArcData(updated);
5133
+ // transitions
5134
+ $$.unexpandArc(updated.data.id);
5135
+ $$.api.revert();
5136
+ $$.revertLegend();
5137
+ $$.hideTooltip();
5138
+ $$.config.data_onmouseout(arcData, this);
5139
+ }
4884
5140
  } : null)
4885
5141
  .on('click', config.interaction_enabled ? function (d, i) {
4886
- var updated = $$.updateAngle(d),
5142
+ var updated = $$.updateAngle(d), arcData;
5143
+ if (updated) {
4887
5144
  arcData = $$.convertToArcData(updated);
4888
- if ($$.toggleShape) { $$.toggleShape(this, arcData, i); }
4889
- $$.config.data_onclick.call($$.api, arcData, this);
5145
+ if ($$.toggleShape) {
5146
+ $$.toggleShape(this, arcData, i);
5147
+ }
5148
+ $$.config.data_onclick.call($$.api, arcData, this);
5149
+ }
4890
5150
  } : null)
4891
5151
  .each(function () { $$.transiting = true; })
4892
5152
  .transition().duration(duration)
@@ -4942,8 +5202,8 @@
4942
5202
  .attr("d", function () {
4943
5203
  var d = {
4944
5204
  data: [{value: config.gauge_max}],
4945
- startAngle: -1 * (Math.PI / 2),
4946
- endAngle: Math.PI / 2
5205
+ startAngle: config.gauge_startingAngle,
5206
+ endAngle: -1 * config.gauge_startingAngle
4947
5207
  };
4948
5208
  return $$.getArc(d, true, true);
4949
5209
  });
@@ -4951,11 +5211,11 @@
4951
5211
  .attr("dy", ".75em")
4952
5212
  .text(config.gauge_label_show ? config.gauge_units : '');
4953
5213
  $$.arcs.select('.' + CLASS.chartArcsGaugeMin)
4954
- .attr("dx", -1 * ($$.innerRadius + (($$.radius - $$.innerRadius) / 2)) + "px")
5214
+ .attr("dx", -1 * ($$.innerRadius + (($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2))) + "px")
4955
5215
  .attr("dy", "1.2em")
4956
5216
  .text(config.gauge_label_show ? config.gauge_min : '');
4957
5217
  $$.arcs.select('.' + CLASS.chartArcsGaugeMax)
4958
- .attr("dx", $$.innerRadius + (($$.radius - $$.innerRadius) / 2) + "px")
5218
+ .attr("dx", $$.innerRadius + (($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2)) + "px")
4959
5219
  .attr("dy", "1.2em")
4960
5220
  .text(config.gauge_label_show ? config.gauge_max : '');
4961
5221
  }
@@ -4998,16 +5258,23 @@
4998
5258
  $$.mainRegion = $$.main.select('.' + CLASS.regions).selectAll('.' + CLASS.region)
4999
5259
  .data(config.regions);
5000
5260
  $$.mainRegion.enter().append('g')
5001
- .attr('class', $$.classRegion.bind($$))
5002
5261
  .append('rect')
5003
5262
  .style("fill-opacity", 0);
5263
+ $$.mainRegion
5264
+ .attr('class', $$.classRegion.bind($$));
5004
5265
  $$.mainRegion.exit().transition().duration(duration)
5005
5266
  .style("opacity", 0)
5006
5267
  .remove();
5007
5268
  };
5008
5269
  c3_chart_internal_fn.redrawRegion = function (withTransition) {
5009
5270
  var $$ = this,
5010
- regions = $$.mainRegion.selectAll('rect'),
5271
+ regions = $$.mainRegion.selectAll('rect').each(function () {
5272
+ // data is binded to g and it's not transferred to rect (child node) automatically,
5273
+ // then data of each rect has to be updated manually.
5274
+ // TODO: there should be more efficient way to solve this?
5275
+ var parentData = $$.d3.select(this.parentNode).datum();
5276
+ $$.d3.select(this).datum(parentData);
5277
+ }),
5011
5278
  x = $$.regionX.bind($$),
5012
5279
  y = $$.regionY.bind($$),
5013
5280
  w = $$.regionWidth.bind($$),
@@ -5167,7 +5434,7 @@
5167
5434
  };
5168
5435
  c3_chart_internal_fn.unselectPoint = function (target, d, i) {
5169
5436
  var $$ = this;
5170
- $$.config.data_onunselected(d, target.node());
5437
+ $$.config.data_onunselected.call($$.api, d, target.node());
5171
5438
  // remove selected-circle from low layer g
5172
5439
  $$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i)
5173
5440
  .transition().duration(100).attr('r', 0)
@@ -5179,14 +5446,18 @@
5179
5446
  c3_chart_internal_fn.selectPath = function (target, d) {
5180
5447
  var $$ = this;
5181
5448
  $$.config.data_onselected.call($$, d, target.node());
5182
- target.transition().duration(100)
5183
- .style("fill", function () { return $$.d3.rgb($$.color(d)).brighter(0.75); });
5449
+ if ($$.config.interaction_brighten) {
5450
+ target.transition().duration(100)
5451
+ .style("fill", function () { return $$.d3.rgb($$.color(d)).brighter(0.75); });
5452
+ }
5184
5453
  };
5185
5454
  c3_chart_internal_fn.unselectPath = function (target, d) {
5186
5455
  var $$ = this;
5187
5456
  $$.config.data_onunselected.call($$, d, target.node());
5188
- target.transition().duration(100)
5189
- .style("fill", function () { return $$.color(d); });
5457
+ if ($$.config.interaction_brighten) {
5458
+ target.transition().duration(100)
5459
+ .style("fill", function () { return $$.color(d); });
5460
+ }
5190
5461
  };
5191
5462
  c3_chart_internal_fn.togglePath = function (selected, target, d, i) {
5192
5463
  selected ? this.selectPath(target, d, i) : this.unselectPath(target, d, i);
@@ -5236,9 +5507,10 @@
5236
5507
  };
5237
5508
  c3_chart_internal_fn.initSubchart = function () {
5238
5509
  var $$ = this, config = $$.config,
5239
- context = $$.context = $$.svg.append("g").attr("transform", $$.getTranslate('context'));
5510
+ context = $$.context = $$.svg.append("g").attr("transform", $$.getTranslate('context')),
5511
+ visibility = config.subchart_show ? 'visible' : 'hidden';
5240
5512
 
5241
- context.style('visibility', config.subchart_show ? 'visible' : 'hidden');
5513
+ context.style('visibility', visibility);
5242
5514
 
5243
5515
  // Define g for chart area
5244
5516
  context.append('g')
@@ -5264,7 +5536,8 @@
5264
5536
  $$.axes.subx = context.append("g")
5265
5537
  .attr("class", CLASS.axisX)
5266
5538
  .attr("transform", $$.getTranslate('subx'))
5267
- .attr("clip-path", config.axis_rotated ? "" : $$.clipPathForXAxis);
5539
+ .attr("clip-path", config.axis_rotated ? "" : $$.clipPathForXAxis)
5540
+ .style("visibility", config.subchart_axis_x_show ? visibility : 'hidden');
5268
5541
  };
5269
5542
  c3_chart_internal_fn.updateTargetsForSubchart = function (targets) {
5270
5543
  var $$ = this, context = $$.context, config = $$.config,
@@ -5321,7 +5594,7 @@
5321
5594
  .remove();
5322
5595
  };
5323
5596
  c3_chart_internal_fn.redrawBarForSubchart = function (drawBarOnSub, withTransition, duration) {
5324
- (withTransition ? this.contextBar.transition().duration(duration) : this.contextBar)
5597
+ (withTransition ? this.contextBar.transition(Math.random().toString()).duration(duration) : this.contextBar)
5325
5598
  .attr('d', drawBarOnSub)
5326
5599
  .style('opacity', 1);
5327
5600
  };
@@ -5339,7 +5612,7 @@
5339
5612
  .remove();
5340
5613
  };
5341
5614
  c3_chart_internal_fn.redrawLineForSubchart = function (drawLineOnSub, withTransition, duration) {
5342
- (withTransition ? this.contextLine.transition().duration(duration) : this.contextLine)
5615
+ (withTransition ? this.contextLine.transition(Math.random().toString()).duration(duration) : this.contextLine)
5343
5616
  .attr("d", drawLineOnSub)
5344
5617
  .style('opacity', 1);
5345
5618
  };
@@ -5358,7 +5631,7 @@
5358
5631
  .remove();
5359
5632
  };
5360
5633
  c3_chart_internal_fn.redrawAreaForSubchart = function (drawAreaOnSub, withTransition, duration) {
5361
- (withTransition ? this.contextArea.transition().duration(duration) : this.contextArea)
5634
+ (withTransition ? this.contextArea.transition(Math.random().toString()).duration(duration) : this.contextArea)
5362
5635
  .attr("d", drawAreaOnSub)
5363
5636
  .style("fill", this.color)
5364
5637
  .style("opacity", this.orgAreaOpacity);
@@ -5458,12 +5731,18 @@
5458
5731
  return [extent[0], Math.max($$.getMaxDataCount() / extent[1], extent[1])];
5459
5732
  };
5460
5733
  $$.zoom.updateScaleExtent = function () {
5461
- var ratio = diffDomain($$.x.orgDomain()) / diffDomain($$.orgXDomain),
5734
+ var ratio = diffDomain($$.x.orgDomain()) / diffDomain($$.getZoomDomain()),
5462
5735
  extent = this.orgScaleExtent();
5463
5736
  this.scaleExtent([extent[0] * ratio, extent[1] * ratio]);
5464
5737
  return this;
5465
5738
  };
5466
5739
  };
5740
+ c3_chart_internal_fn.getZoomDomain = function () {
5741
+ var $$ = this, config = $$.config, d3 = $$.d3,
5742
+ min = d3.min([$$.orgXDomain[0], config.zoom_x_min]),
5743
+ max = d3.max([$$.orgXDomain[1], config.zoom_x_max]);
5744
+ return [min, max];
5745
+ };
5467
5746
  c3_chart_internal_fn.updateZoom = function () {
5468
5747
  var $$ = this, z = $$.config.zoom_enabled ? $$.zoom : function () {};
5469
5748
  $$.main.select('.' + CLASS.zoomRect).call(z).on("dblclick.zoom", null);
@@ -5633,6 +5912,7 @@
5633
5912
  defocused: 'c3-defocused',
5634
5913
  region: 'c3-region',
5635
5914
  regions: 'c3-regions',
5915
+ title: 'c3-title',
5636
5916
  tooltipContainer: 'c3-tooltip-container',
5637
5917
  tooltip: 'c3-tooltip',
5638
5918
  tooltipName: 'c3-tooltip-name',
@@ -5805,10 +6085,10 @@
5805
6085
  return d[1] - d[0];
5806
6086
  },
5807
6087
  isEmpty = c3_chart_internal_fn.isEmpty = function (o) {
5808
- return !o || (isString(o) && o.length === 0) || (typeof o === 'object' && Object.keys(o).length === 0);
6088
+ return typeof o === 'undefined' || o === null || (isString(o) && o.length === 0) || (typeof o === 'object' && Object.keys(o).length === 0);
5809
6089
  },
5810
6090
  notEmpty = c3_chart_internal_fn.notEmpty = function (o) {
5811
- return Object.keys(o).length > 0;
6091
+ return !c3_chart_internal_fn.isEmpty(o);
5812
6092
  },
5813
6093
  getOption = c3_chart_internal_fn.getOption = function (options, key, defaultValue) {
5814
6094
  return isDefined(options[key]) ? options[key] : defaultValue;
@@ -5820,6 +6100,9 @@
5820
6100
  });
5821
6101
  return found;
5822
6102
  },
6103
+ sanitise = c3_chart_internal_fn.sanitise = function (str) {
6104
+ return typeof str === 'string' ? str.replace(/</g, '&lt;').replace(/>/g, '&gt;') : str;
6105
+ },
5823
6106
  getPathBox = c3_chart_internal_fn.getPathBox = function (path) {
5824
6107
  var box = path.getBoundingClientRect(),
5825
6108
  items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)],
@@ -5962,12 +6245,48 @@
5962
6245
  $$.redraw({withUpdateXDomain: true});
5963
6246
  };
5964
6247
 
6248
+ c3_chart_fn.zoom.max = function (max) {
6249
+ var $$ = this.internal, config = $$.config, d3 = $$.d3;
6250
+ if (max === 0 || max) {
6251
+ config.zoom_x_max = d3.max([$$.orgXDomain[1], max]);
6252
+ }
6253
+ else {
6254
+ return config.zoom_x_max;
6255
+ }
6256
+ };
6257
+
6258
+ c3_chart_fn.zoom.min = function (min) {
6259
+ var $$ = this.internal, config = $$.config, d3 = $$.d3;
6260
+ if (min === 0 || min) {
6261
+ config.zoom_x_min = d3.min([$$.orgXDomain[0], min]);
6262
+ }
6263
+ else {
6264
+ return config.zoom_x_min;
6265
+ }
6266
+ };
6267
+
6268
+ c3_chart_fn.zoom.range = function (range) {
6269
+ if (arguments.length) {
6270
+ if (isDefined(range.max)) { this.domain.max(range.max); }
6271
+ if (isDefined(range.min)) { this.domain.min(range.min); }
6272
+ } else {
6273
+ return {
6274
+ max: this.domain.max(),
6275
+ min: this.domain.min()
6276
+ };
6277
+ }
6278
+ };
6279
+
5965
6280
  c3_chart_fn.load = function (args) {
5966
6281
  var $$ = this.internal, config = $$.config;
5967
6282
  // update xs if specified
5968
6283
  if (args.xs) {
5969
6284
  $$.addXs(args.xs);
5970
6285
  }
6286
+ // update names if exists
6287
+ if ('names' in args) {
6288
+ c3_chart_fn.data.names.bind(this)(args.names);
6289
+ }
5971
6290
  // update classes if exists
5972
6291
  if ('classes' in args) {
5973
6292
  Object.keys(args.classes).forEach(function (id) {
@@ -6224,7 +6543,7 @@
6224
6543
  translateX = diffDomain(domain) / 2;
6225
6544
  }
6226
6545
  }
6227
- } else if (flow.orgDataCount === 1 || flowStart.x === flowEnd.x) {
6546
+ } else if (flow.orgDataCount === 1 || (flowStart && flowStart.x) === (flowEnd && flowEnd.x)) {
6228
6547
  translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
6229
6548
  } else {
6230
6549
  if ($$.isTimeSeries()) {
@@ -6236,9 +6555,7 @@
6236
6555
  scaleX = (diffDomain(orgDomain) / diffDomain(domain));
6237
6556
  transform = 'translate(' + translateX + ',0) scale(' + scaleX + ',1)';
6238
6557
 
6239
- // hide tooltip
6240
6558
  $$.hideXGridFocus();
6241
- $$.hideTooltip();
6242
6559
 
6243
6560
  d3.transition().ease('linear').duration(durationForFlow).each(function () {
6244
6561
  wait.add($$.axes.x.transition().call($$.xAxis));
@@ -6624,7 +6941,22 @@
6624
6941
  var $$ = this.internal;
6625
6942
 
6626
6943
  window.clearInterval($$.intervalForObserveInserted);
6627
- window.onresize = null;
6944
+
6945
+ if ($$.resizeTimeout !== undefined) {
6946
+ window.clearTimeout($$.resizeTimeout);
6947
+ }
6948
+
6949
+ if (window.detachEvent) {
6950
+ window.detachEvent('onresize', $$.resizeFunction);
6951
+ } else if (window.removeEventListener) {
6952
+ window.removeEventListener('resize', $$.resizeFunction);
6953
+ } else {
6954
+ var wrapper = window.onresize;
6955
+ // check if no one else removed our wrapper and remove our resizeFunction from it
6956
+ if (wrapper && wrapper.add && wrapper.remove) {
6957
+ wrapper.remove($$.resizeFunction);
6958
+ }
6959
+ }
6628
6960
 
6629
6961
  $$.selectChart.classed('c3', false).html("");
6630
6962
 
@@ -6666,10 +6998,14 @@
6666
6998
  // emulate mouse events to show
6667
6999
  $$.dispatchEvent('mouseover', index, mouse);
6668
7000
  $$.dispatchEvent('mousemove', index, mouse);
7001
+
7002
+ $$.config.tooltip_onshow.call($$, args.data);
6669
7003
  };
6670
7004
  c3_chart_fn.tooltip.hide = function () {
6671
7005
  // TODO: get target data by checking the state of focus
6672
7006
  this.internal.dispatchEvent('mouseout', 0);
7007
+
7008
+ this.internal.config.tooltip_onhide.call(this);
6673
7009
  };
6674
7010
 
6675
7011
  // Features:
@@ -7012,6 +7348,8 @@
7012
7348
  return ua.indexOf('Chrome') >= 0;
7013
7349
  };
7014
7350
 
7351
+ /* jshint ignore:start */
7352
+
7015
7353
  // PhantomJS doesn't have support for Function.prototype.bind, which has caused confusion. Use
7016
7354
  // this polyfill to avoid the confusion.
7017
7355
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Polyfill
@@ -7038,8 +7376,823 @@
7038
7376
  };
7039
7377
  }
7040
7378
 
7379
+ //SVGPathSeg API polyfill
7380
+ //https://github.com/progers/pathseg
7381
+ //
7382
+ //This is a drop-in replacement for the SVGPathSeg and SVGPathSegList APIs that were removed from
7383
+ //SVG2 (https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html), including the latest spec
7384
+ //changes which were implemented in Firefox 43 and Chrome 46.
7385
+ //Chrome 48 removes these APIs, so this polyfill is required.
7386
+
7387
+ (function() { "use strict";
7388
+ if (!("SVGPathSeg" in window)) {
7389
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg
7390
+ window.SVGPathSeg = function(type, typeAsLetter, owningPathSegList) {
7391
+ this.pathSegType = type;
7392
+ this.pathSegTypeAsLetter = typeAsLetter;
7393
+ this._owningPathSegList = owningPathSegList;
7394
+ }
7395
+
7396
+ SVGPathSeg.PATHSEG_UNKNOWN = 0;
7397
+ SVGPathSeg.PATHSEG_CLOSEPATH = 1;
7398
+ SVGPathSeg.PATHSEG_MOVETO_ABS = 2;
7399
+ SVGPathSeg.PATHSEG_MOVETO_REL = 3;
7400
+ SVGPathSeg.PATHSEG_LINETO_ABS = 4;
7401
+ SVGPathSeg.PATHSEG_LINETO_REL = 5;
7402
+ SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;
7403
+ SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;
7404
+ SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;
7405
+ SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;
7406
+ SVGPathSeg.PATHSEG_ARC_ABS = 10;
7407
+ SVGPathSeg.PATHSEG_ARC_REL = 11;
7408
+ SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;
7409
+ SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;
7410
+ SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;
7411
+ SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;
7412
+ SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
7413
+ SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
7414
+ SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
7415
+ SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
7416
+
7417
+ // Notify owning PathSegList on any changes so they can be synchronized back to the path element.
7418
+ SVGPathSeg.prototype._segmentChanged = function() {
7419
+ if (this._owningPathSegList)
7420
+ this._owningPathSegList.segmentChanged(this);
7421
+ }
7422
+
7423
+ window.SVGPathSegClosePath = function(owningPathSegList) {
7424
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CLOSEPATH, "z", owningPathSegList);
7425
+ }
7426
+ SVGPathSegClosePath.prototype = Object.create(SVGPathSeg.prototype);
7427
+ SVGPathSegClosePath.prototype.toString = function() { return "[object SVGPathSegClosePath]"; }
7428
+ SVGPathSegClosePath.prototype._asPathString = function() { return this.pathSegTypeAsLetter; }
7429
+ SVGPathSegClosePath.prototype.clone = function() { return new SVGPathSegClosePath(undefined); }
7430
+
7431
+ window.SVGPathSegMovetoAbs = function(owningPathSegList, x, y) {
7432
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_MOVETO_ABS, "M", owningPathSegList);
7433
+ this._x = x;
7434
+ this._y = y;
7435
+ }
7436
+ SVGPathSegMovetoAbs.prototype = Object.create(SVGPathSeg.prototype);
7437
+ SVGPathSegMovetoAbs.prototype.toString = function() { return "[object SVGPathSegMovetoAbs]"; }
7438
+ SVGPathSegMovetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
7439
+ SVGPathSegMovetoAbs.prototype.clone = function() { return new SVGPathSegMovetoAbs(undefined, this._x, this._y); }
7440
+ Object.defineProperty(SVGPathSegMovetoAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7441
+ Object.defineProperty(SVGPathSegMovetoAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7442
+
7443
+ window.SVGPathSegMovetoRel = function(owningPathSegList, x, y) {
7444
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_MOVETO_REL, "m", owningPathSegList);
7445
+ this._x = x;
7446
+ this._y = y;
7447
+ }
7448
+ SVGPathSegMovetoRel.prototype = Object.create(SVGPathSeg.prototype);
7449
+ SVGPathSegMovetoRel.prototype.toString = function() { return "[object SVGPathSegMovetoRel]"; }
7450
+ SVGPathSegMovetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
7451
+ SVGPathSegMovetoRel.prototype.clone = function() { return new SVGPathSegMovetoRel(undefined, this._x, this._y); }
7452
+ Object.defineProperty(SVGPathSegMovetoRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7453
+ Object.defineProperty(SVGPathSegMovetoRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7454
+
7455
+ window.SVGPathSegLinetoAbs = function(owningPathSegList, x, y) {
7456
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_ABS, "L", owningPathSegList);
7457
+ this._x = x;
7458
+ this._y = y;
7459
+ }
7460
+ SVGPathSegLinetoAbs.prototype = Object.create(SVGPathSeg.prototype);
7461
+ SVGPathSegLinetoAbs.prototype.toString = function() { return "[object SVGPathSegLinetoAbs]"; }
7462
+ SVGPathSegLinetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
7463
+ SVGPathSegLinetoAbs.prototype.clone = function() { return new SVGPathSegLinetoAbs(undefined, this._x, this._y); }
7464
+ Object.defineProperty(SVGPathSegLinetoAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7465
+ Object.defineProperty(SVGPathSegLinetoAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7466
+
7467
+ window.SVGPathSegLinetoRel = function(owningPathSegList, x, y) {
7468
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_REL, "l", owningPathSegList);
7469
+ this._x = x;
7470
+ this._y = y;
7471
+ }
7472
+ SVGPathSegLinetoRel.prototype = Object.create(SVGPathSeg.prototype);
7473
+ SVGPathSegLinetoRel.prototype.toString = function() { return "[object SVGPathSegLinetoRel]"; }
7474
+ SVGPathSegLinetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
7475
+ SVGPathSegLinetoRel.prototype.clone = function() { return new SVGPathSegLinetoRel(undefined, this._x, this._y); }
7476
+ Object.defineProperty(SVGPathSegLinetoRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7477
+ Object.defineProperty(SVGPathSegLinetoRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7478
+
7479
+ window.SVGPathSegCurvetoCubicAbs = function(owningPathSegList, x, y, x1, y1, x2, y2) {
7480
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, "C", owningPathSegList);
7481
+ this._x = x;
7482
+ this._y = y;
7483
+ this._x1 = x1;
7484
+ this._y1 = y1;
7485
+ this._x2 = x2;
7486
+ this._y2 = y2;
7487
+ }
7488
+ SVGPathSegCurvetoCubicAbs.prototype = Object.create(SVGPathSeg.prototype);
7489
+ SVGPathSegCurvetoCubicAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicAbs]"; }
7490
+ SVGPathSegCurvetoCubicAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
7491
+ SVGPathSegCurvetoCubicAbs.prototype.clone = function() { return new SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }
7492
+ Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7493
+ Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7494
+ Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
7495
+ Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
7496
+ Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
7497
+ Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
7498
+
7499
+ window.SVGPathSegCurvetoCubicRel = function(owningPathSegList, x, y, x1, y1, x2, y2) {
7500
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, "c", owningPathSegList);
7501
+ this._x = x;
7502
+ this._y = y;
7503
+ this._x1 = x1;
7504
+ this._y1 = y1;
7505
+ this._x2 = x2;
7506
+ this._y2 = y2;
7507
+ }
7508
+ SVGPathSegCurvetoCubicRel.prototype = Object.create(SVGPathSeg.prototype);
7509
+ SVGPathSegCurvetoCubicRel.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicRel]"; }
7510
+ SVGPathSegCurvetoCubicRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
7511
+ SVGPathSegCurvetoCubicRel.prototype.clone = function() { return new SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }
7512
+ Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7513
+ Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7514
+ Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
7515
+ Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
7516
+ Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
7517
+ Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
7518
+
7519
+ window.SVGPathSegCurvetoQuadraticAbs = function(owningPathSegList, x, y, x1, y1) {
7520
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, "Q", owningPathSegList);
7521
+ this._x = x;
7522
+ this._y = y;
7523
+ this._x1 = x1;
7524
+ this._y1 = y1;
7525
+ }
7526
+ SVGPathSegCurvetoQuadraticAbs.prototype = Object.create(SVGPathSeg.prototype);
7527
+ SVGPathSegCurvetoQuadraticAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticAbs]"; }
7528
+ SVGPathSegCurvetoQuadraticAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y; }
7529
+ SVGPathSegCurvetoQuadraticAbs.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1); }
7530
+ Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7531
+ Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7532
+ Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
7533
+ Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
7534
+
7535
+ window.SVGPathSegCurvetoQuadraticRel = function(owningPathSegList, x, y, x1, y1) {
7536
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, "q", owningPathSegList);
7537
+ this._x = x;
7538
+ this._y = y;
7539
+ this._x1 = x1;
7540
+ this._y1 = y1;
7541
+ }
7542
+ SVGPathSegCurvetoQuadraticRel.prototype = Object.create(SVGPathSeg.prototype);
7543
+ SVGPathSegCurvetoQuadraticRel.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticRel]"; }
7544
+ SVGPathSegCurvetoQuadraticRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y; }
7545
+ SVGPathSegCurvetoQuadraticRel.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1); }
7546
+ Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7547
+ Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7548
+ Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
7549
+ Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
7550
+
7551
+ window.SVGPathSegArcAbs = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
7552
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_ARC_ABS, "A", owningPathSegList);
7553
+ this._x = x;
7554
+ this._y = y;
7555
+ this._r1 = r1;
7556
+ this._r2 = r2;
7557
+ this._angle = angle;
7558
+ this._largeArcFlag = largeArcFlag;
7559
+ this._sweepFlag = sweepFlag;
7560
+ }
7561
+ SVGPathSegArcAbs.prototype = Object.create(SVGPathSeg.prototype);
7562
+ SVGPathSegArcAbs.prototype.toString = function() { return "[object SVGPathSegArcAbs]"; }
7563
+ SVGPathSegArcAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y; }
7564
+ SVGPathSegArcAbs.prototype.clone = function() { return new SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }
7565
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7566
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7567
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "r1", { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true });
7568
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "r2", { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true });
7569
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "angle", { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true });
7570
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "largeArcFlag", { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true });
7571
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "sweepFlag", { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true });
7572
+
7573
+ window.SVGPathSegArcRel = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
7574
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_ARC_REL, "a", owningPathSegList);
7575
+ this._x = x;
7576
+ this._y = y;
7577
+ this._r1 = r1;
7578
+ this._r2 = r2;
7579
+ this._angle = angle;
7580
+ this._largeArcFlag = largeArcFlag;
7581
+ this._sweepFlag = sweepFlag;
7582
+ }
7583
+ SVGPathSegArcRel.prototype = Object.create(SVGPathSeg.prototype);
7584
+ SVGPathSegArcRel.prototype.toString = function() { return "[object SVGPathSegArcRel]"; }
7585
+ SVGPathSegArcRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y; }
7586
+ SVGPathSegArcRel.prototype.clone = function() { return new SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }
7587
+ Object.defineProperty(SVGPathSegArcRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7588
+ Object.defineProperty(SVGPathSegArcRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7589
+ Object.defineProperty(SVGPathSegArcRel.prototype, "r1", { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true });
7590
+ Object.defineProperty(SVGPathSegArcRel.prototype, "r2", { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true });
7591
+ Object.defineProperty(SVGPathSegArcRel.prototype, "angle", { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true });
7592
+ Object.defineProperty(SVGPathSegArcRel.prototype, "largeArcFlag", { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true });
7593
+ Object.defineProperty(SVGPathSegArcRel.prototype, "sweepFlag", { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true });
7594
+
7595
+ window.SVGPathSegLinetoHorizontalAbs = function(owningPathSegList, x) {
7596
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, "H", owningPathSegList);
7597
+ this._x = x;
7598
+ }
7599
+ SVGPathSegLinetoHorizontalAbs.prototype = Object.create(SVGPathSeg.prototype);
7600
+ SVGPathSegLinetoHorizontalAbs.prototype.toString = function() { return "[object SVGPathSegLinetoHorizontalAbs]"; }
7601
+ SVGPathSegLinetoHorizontalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x; }
7602
+ SVGPathSegLinetoHorizontalAbs.prototype.clone = function() { return new SVGPathSegLinetoHorizontalAbs(undefined, this._x); }
7603
+ Object.defineProperty(SVGPathSegLinetoHorizontalAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7604
+
7605
+ window.SVGPathSegLinetoHorizontalRel = function(owningPathSegList, x) {
7606
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, "h", owningPathSegList);
7607
+ this._x = x;
7608
+ }
7609
+ SVGPathSegLinetoHorizontalRel.prototype = Object.create(SVGPathSeg.prototype);
7610
+ SVGPathSegLinetoHorizontalRel.prototype.toString = function() { return "[object SVGPathSegLinetoHorizontalRel]"; }
7611
+ SVGPathSegLinetoHorizontalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x; }
7612
+ SVGPathSegLinetoHorizontalRel.prototype.clone = function() { return new SVGPathSegLinetoHorizontalRel(undefined, this._x); }
7613
+ Object.defineProperty(SVGPathSegLinetoHorizontalRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7614
+
7615
+ window.SVGPathSegLinetoVerticalAbs = function(owningPathSegList, y) {
7616
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, "V", owningPathSegList);
7617
+ this._y = y;
7618
+ }
7619
+ SVGPathSegLinetoVerticalAbs.prototype = Object.create(SVGPathSeg.prototype);
7620
+ SVGPathSegLinetoVerticalAbs.prototype.toString = function() { return "[object SVGPathSegLinetoVerticalAbs]"; }
7621
+ SVGPathSegLinetoVerticalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._y; }
7622
+ SVGPathSegLinetoVerticalAbs.prototype.clone = function() { return new SVGPathSegLinetoVerticalAbs(undefined, this._y); }
7623
+ Object.defineProperty(SVGPathSegLinetoVerticalAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7624
+
7625
+ window.SVGPathSegLinetoVerticalRel = function(owningPathSegList, y) {
7626
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, "v", owningPathSegList);
7627
+ this._y = y;
7628
+ }
7629
+ SVGPathSegLinetoVerticalRel.prototype = Object.create(SVGPathSeg.prototype);
7630
+ SVGPathSegLinetoVerticalRel.prototype.toString = function() { return "[object SVGPathSegLinetoVerticalRel]"; }
7631
+ SVGPathSegLinetoVerticalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._y; }
7632
+ SVGPathSegLinetoVerticalRel.prototype.clone = function() { return new SVGPathSegLinetoVerticalRel(undefined, this._y); }
7633
+ Object.defineProperty(SVGPathSegLinetoVerticalRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7634
+
7635
+ window.SVGPathSegCurvetoCubicSmoothAbs = function(owningPathSegList, x, y, x2, y2) {
7636
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, "S", owningPathSegList);
7637
+ this._x = x;
7638
+ this._y = y;
7639
+ this._x2 = x2;
7640
+ this._y2 = y2;
7641
+ }
7642
+ SVGPathSegCurvetoCubicSmoothAbs.prototype = Object.create(SVGPathSeg.prototype);
7643
+ SVGPathSegCurvetoCubicSmoothAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicSmoothAbs]"; }
7644
+ SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
7645
+ SVGPathSegCurvetoCubicSmoothAbs.prototype.clone = function() { return new SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2); }
7646
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7647
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7648
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
7649
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
7650
+
7651
+ window.SVGPathSegCurvetoCubicSmoothRel = function(owningPathSegList, x, y, x2, y2) {
7652
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, "s", owningPathSegList);
7653
+ this._x = x;
7654
+ this._y = y;
7655
+ this._x2 = x2;
7656
+ this._y2 = y2;
7657
+ }
7658
+ SVGPathSegCurvetoCubicSmoothRel.prototype = Object.create(SVGPathSeg.prototype);
7659
+ SVGPathSegCurvetoCubicSmoothRel.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicSmoothRel]"; }
7660
+ SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
7661
+ SVGPathSegCurvetoCubicSmoothRel.prototype.clone = function() { return new SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2); }
7662
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7663
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7664
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
7665
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
7666
+
7667
+ window.SVGPathSegCurvetoQuadraticSmoothAbs = function(owningPathSegList, x, y) {
7668
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, "T", owningPathSegList);
7669
+ this._x = x;
7670
+ this._y = y;
7671
+ }
7672
+ SVGPathSegCurvetoQuadraticSmoothAbs.prototype = Object.create(SVGPathSeg.prototype);
7673
+ SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticSmoothAbs]"; }
7674
+ SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
7675
+ SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y); }
7676
+ Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7677
+ Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7678
+
7679
+ window.SVGPathSegCurvetoQuadraticSmoothRel = function(owningPathSegList, x, y) {
7680
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, "t", owningPathSegList);
7681
+ this._x = x;
7682
+ this._y = y;
7683
+ }
7684
+ SVGPathSegCurvetoQuadraticSmoothRel.prototype = Object.create(SVGPathSeg.prototype);
7685
+ SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticSmoothRel]"; }
7686
+ SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
7687
+ SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y); }
7688
+ Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
7689
+ Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
7690
+
7691
+ // Add createSVGPathSeg* functions to SVGPathElement.
7692
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathElement.
7693
+ SVGPathElement.prototype.createSVGPathSegClosePath = function() { return new SVGPathSegClosePath(undefined); }
7694
+ SVGPathElement.prototype.createSVGPathSegMovetoAbs = function(x, y) { return new SVGPathSegMovetoAbs(undefined, x, y); }
7695
+ SVGPathElement.prototype.createSVGPathSegMovetoRel = function(x, y) { return new SVGPathSegMovetoRel(undefined, x, y); }
7696
+ SVGPathElement.prototype.createSVGPathSegLinetoAbs = function(x, y) { return new SVGPathSegLinetoAbs(undefined, x, y); }
7697
+ SVGPathElement.prototype.createSVGPathSegLinetoRel = function(x, y) { return new SVGPathSegLinetoRel(undefined, x, y); }
7698
+ SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function(x, y, x1, y1, x2, y2) { return new SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2); }
7699
+ SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function(x, y, x1, y1, x2, y2) { return new SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2); }
7700
+ SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function(x, y, x1, y1) { return new SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1); }
7701
+ SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function(x, y, x1, y1) { return new SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1); }
7702
+ SVGPathElement.prototype.createSVGPathSegArcAbs = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }
7703
+ SVGPathElement.prototype.createSVGPathSegArcRel = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }
7704
+ SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function(x) { return new SVGPathSegLinetoHorizontalAbs(undefined, x); }
7705
+ SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function(x) { return new SVGPathSegLinetoHorizontalRel(undefined, x); }
7706
+ SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function(y) { return new SVGPathSegLinetoVerticalAbs(undefined, y); }
7707
+ SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function(y) { return new SVGPathSegLinetoVerticalRel(undefined, y); }
7708
+ SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function(x, y, x2, y2) { return new SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2); }
7709
+ SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function(x, y, x2, y2) { return new SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2); }
7710
+ SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function(x, y) { return new SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y); }
7711
+ SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function(x, y) { return new SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y); }
7712
+ }
7713
+
7714
+ if (!("SVGPathSegList" in window)) {
7715
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList
7716
+ window.SVGPathSegList = function(pathElement) {
7717
+ this._pathElement = pathElement;
7718
+ this._list = this._parsePath(this._pathElement.getAttribute("d"));
7719
+
7720
+ // Use a MutationObserver to catch changes to the path's "d" attribute.
7721
+ this._mutationObserverConfig = { "attributes": true, "attributeFilter": ["d"] };
7722
+ this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this));
7723
+ this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
7724
+ }
7725
+
7726
+ Object.defineProperty(SVGPathSegList.prototype, "numberOfItems", {
7727
+ get: function() {
7728
+ this._checkPathSynchronizedToList();
7729
+ return this._list.length;
7730
+ },
7731
+ enumerable: true
7732
+ });
7733
+
7734
+ // Add the pathSegList accessors to SVGPathElement.
7735
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData
7736
+ Object.defineProperty(SVGPathElement.prototype, "pathSegList", {
7737
+ get: function() {
7738
+ if (!this._pathSegList)
7739
+ this._pathSegList = new SVGPathSegList(this);
7740
+ return this._pathSegList;
7741
+ },
7742
+ enumerable: true
7743
+ });
7744
+ // FIXME: The following are not implemented and simply return SVGPathElement.pathSegList.
7745
+ Object.defineProperty(SVGPathElement.prototype, "normalizedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
7746
+ Object.defineProperty(SVGPathElement.prototype, "animatedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
7747
+ Object.defineProperty(SVGPathElement.prototype, "animatedNormalizedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
7748
+
7749
+ // Process any pending mutations to the path element and update the list as needed.
7750
+ // This should be the first call of all public functions and is needed because
7751
+ // MutationObservers are not synchronous so we can have pending asynchronous mutations.
7752
+ SVGPathSegList.prototype._checkPathSynchronizedToList = function() {
7753
+ this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords());
7754
+ }
7755
+
7756
+ SVGPathSegList.prototype._updateListFromPathMutations = function(mutationRecords) {
7757
+ if (!this._pathElement)
7758
+ return;
7759
+ var hasPathMutations = false;
7760
+ mutationRecords.forEach(function(record) {
7761
+ if (record.attributeName == "d")
7762
+ hasPathMutations = true;
7763
+ });
7764
+ if (hasPathMutations)
7765
+ this._list = this._parsePath(this._pathElement.getAttribute("d"));
7766
+ }
7767
+
7768
+ // Serialize the list and update the path's 'd' attribute.
7769
+ SVGPathSegList.prototype._writeListToPath = function() {
7770
+ this._pathElementMutationObserver.disconnect();
7771
+ this._pathElement.setAttribute("d", SVGPathSegList._pathSegArrayAsString(this._list));
7772
+ this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
7773
+ }
7774
+
7775
+ // When a path segment changes the list needs to be synchronized back to the path element.
7776
+ SVGPathSegList.prototype.segmentChanged = function(pathSeg) {
7777
+ this._writeListToPath();
7778
+ }
7779
+
7780
+ SVGPathSegList.prototype.clear = function() {
7781
+ this._checkPathSynchronizedToList();
7782
+
7783
+ this._list.forEach(function(pathSeg) {
7784
+ pathSeg._owningPathSegList = null;
7785
+ });
7786
+ this._list = [];
7787
+ this._writeListToPath();
7788
+ }
7789
+
7790
+ SVGPathSegList.prototype.initialize = function(newItem) {
7791
+ this._checkPathSynchronizedToList();
7792
+
7793
+ this._list = [newItem];
7794
+ newItem._owningPathSegList = this;
7795
+ this._writeListToPath();
7796
+ return newItem;
7797
+ }
7798
+
7799
+ SVGPathSegList.prototype._checkValidIndex = function(index) {
7800
+ if (isNaN(index) || index < 0 || index >= this.numberOfItems)
7801
+ throw "INDEX_SIZE_ERR";
7802
+ }
7803
+
7804
+ SVGPathSegList.prototype.getItem = function(index) {
7805
+ this._checkPathSynchronizedToList();
7806
+
7807
+ this._checkValidIndex(index);
7808
+ return this._list[index];
7809
+ }
7810
+
7811
+ SVGPathSegList.prototype.insertItemBefore = function(newItem, index) {
7812
+ this._checkPathSynchronizedToList();
7813
+
7814
+ // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
7815
+ if (index > this.numberOfItems)
7816
+ index = this.numberOfItems;
7817
+ if (newItem._owningPathSegList) {
7818
+ // SVG2 spec says to make a copy.
7819
+ newItem = newItem.clone();
7820
+ }
7821
+ this._list.splice(index, 0, newItem);
7822
+ newItem._owningPathSegList = this;
7823
+ this._writeListToPath();
7824
+ return newItem;
7825
+ }
7826
+
7827
+ SVGPathSegList.prototype.replaceItem = function(newItem, index) {
7828
+ this._checkPathSynchronizedToList();
7829
+
7830
+ if (newItem._owningPathSegList) {
7831
+ // SVG2 spec says to make a copy.
7832
+ newItem = newItem.clone();
7833
+ }
7834
+ this._checkValidIndex(index);
7835
+ this._list[index] = newItem;
7836
+ newItem._owningPathSegList = this;
7837
+ this._writeListToPath();
7838
+ return newItem;
7839
+ }
7840
+
7841
+ SVGPathSegList.prototype.removeItem = function(index) {
7842
+ this._checkPathSynchronizedToList();
7843
+
7844
+ this._checkValidIndex(index);
7845
+ var item = this._list[index];
7846
+ this._list.splice(index, 1);
7847
+ this._writeListToPath();
7848
+ return item;
7849
+ }
7850
+
7851
+ SVGPathSegList.prototype.appendItem = function(newItem) {
7852
+ this._checkPathSynchronizedToList();
7853
+
7854
+ if (newItem._owningPathSegList) {
7855
+ // SVG2 spec says to make a copy.
7856
+ newItem = newItem.clone();
7857
+ }
7858
+ this._list.push(newItem);
7859
+ newItem._owningPathSegList = this;
7860
+ // TODO: Optimize this to just append to the existing attribute.
7861
+ this._writeListToPath();
7862
+ return newItem;
7863
+ }
7864
+
7865
+ SVGPathSegList._pathSegArrayAsString = function(pathSegArray) {
7866
+ var string = "";
7867
+ var first = true;
7868
+ pathSegArray.forEach(function(pathSeg) {
7869
+ if (first) {
7870
+ first = false;
7871
+ string += pathSeg._asPathString();
7872
+ } else {
7873
+ string += " " + pathSeg._asPathString();
7874
+ }
7875
+ });
7876
+ return string;
7877
+ }
7878
+
7879
+ // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp.
7880
+ SVGPathSegList.prototype._parsePath = function(string) {
7881
+ if (!string || string.length == 0)
7882
+ return [];
7883
+
7884
+ var owningPathSegList = this;
7885
+
7886
+ var Builder = function() {
7887
+ this.pathSegList = [];
7888
+ }
7889
+
7890
+ Builder.prototype.appendSegment = function(pathSeg) {
7891
+ this.pathSegList.push(pathSeg);
7892
+ }
7893
+
7894
+ var Source = function(string) {
7895
+ this._string = string;
7896
+ this._currentIndex = 0;
7897
+ this._endIndex = this._string.length;
7898
+ this._previousCommand = SVGPathSeg.PATHSEG_UNKNOWN;
7899
+
7900
+ this._skipOptionalSpaces();
7901
+ }
7902
+
7903
+ Source.prototype._isCurrentSpace = function() {
7904
+ var character = this._string[this._currentIndex];
7905
+ return character <= " " && (character == " " || character == "\n" || character == "\t" || character == "\r" || character == "\f");
7906
+ }
7907
+
7908
+ Source.prototype._skipOptionalSpaces = function() {
7909
+ while (this._currentIndex < this._endIndex && this._isCurrentSpace())
7910
+ this._currentIndex++;
7911
+ return this._currentIndex < this._endIndex;
7912
+ }
7913
+
7914
+ Source.prototype._skipOptionalSpacesOrDelimiter = function() {
7915
+ if (this._currentIndex < this._endIndex && !this._isCurrentSpace() && this._string.charAt(this._currentIndex) != ",")
7916
+ return false;
7917
+ if (this._skipOptionalSpaces()) {
7918
+ if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ",") {
7919
+ this._currentIndex++;
7920
+ this._skipOptionalSpaces();
7921
+ }
7922
+ }
7923
+ return this._currentIndex < this._endIndex;
7924
+ }
7925
+
7926
+ Source.prototype.hasMoreData = function() {
7927
+ return this._currentIndex < this._endIndex;
7928
+ }
7929
+
7930
+ Source.prototype.peekSegmentType = function() {
7931
+ var lookahead = this._string[this._currentIndex];
7932
+ return this._pathSegTypeFromChar(lookahead);
7933
+ }
7934
+
7935
+ Source.prototype._pathSegTypeFromChar = function(lookahead) {
7936
+ switch (lookahead) {
7937
+ case "Z":
7938
+ case "z":
7939
+ return SVGPathSeg.PATHSEG_CLOSEPATH;
7940
+ case "M":
7941
+ return SVGPathSeg.PATHSEG_MOVETO_ABS;
7942
+ case "m":
7943
+ return SVGPathSeg.PATHSEG_MOVETO_REL;
7944
+ case "L":
7945
+ return SVGPathSeg.PATHSEG_LINETO_ABS;
7946
+ case "l":
7947
+ return SVGPathSeg.PATHSEG_LINETO_REL;
7948
+ case "C":
7949
+ return SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;
7950
+ case "c":
7951
+ return SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;
7952
+ case "Q":
7953
+ return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;
7954
+ case "q":
7955
+ return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;
7956
+ case "A":
7957
+ return SVGPathSeg.PATHSEG_ARC_ABS;
7958
+ case "a":
7959
+ return SVGPathSeg.PATHSEG_ARC_REL;
7960
+ case "H":
7961
+ return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;
7962
+ case "h":
7963
+ return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;
7964
+ case "V":
7965
+ return SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;
7966
+ case "v":
7967
+ return SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;
7968
+ case "S":
7969
+ return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
7970
+ case "s":
7971
+ return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;
7972
+ case "T":
7973
+ return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
7974
+ case "t":
7975
+ return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;
7976
+ default:
7977
+ return SVGPathSeg.PATHSEG_UNKNOWN;
7978
+ }
7979
+ }
7980
+
7981
+ Source.prototype._nextCommandHelper = function(lookahead, previousCommand) {
7982
+ // Check for remaining coordinates in the current command.
7983
+ if ((lookahead == "+" || lookahead == "-" || lookahead == "." || (lookahead >= "0" && lookahead <= "9")) && previousCommand != SVGPathSeg.PATHSEG_CLOSEPATH) {
7984
+ if (previousCommand == SVGPathSeg.PATHSEG_MOVETO_ABS)
7985
+ return SVGPathSeg.PATHSEG_LINETO_ABS;
7986
+ if (previousCommand == SVGPathSeg.PATHSEG_MOVETO_REL)
7987
+ return SVGPathSeg.PATHSEG_LINETO_REL;
7988
+ return previousCommand;
7989
+ }
7990
+ return SVGPathSeg.PATHSEG_UNKNOWN;
7991
+ }
7992
+
7993
+ Source.prototype.initialCommandIsMoveTo = function() {
7994
+ // If the path is empty it is still valid, so return true.
7995
+ if (!this.hasMoreData())
7996
+ return true;
7997
+ var command = this.peekSegmentType();
7998
+ // Path must start with moveTo.
7999
+ return command == SVGPathSeg.PATHSEG_MOVETO_ABS || command == SVGPathSeg.PATHSEG_MOVETO_REL;
8000
+ }
8001
+
8002
+ // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp.
8003
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
8004
+ Source.prototype._parseNumber = function() {
8005
+ var exponent = 0;
8006
+ var integer = 0;
8007
+ var frac = 1;
8008
+ var decimal = 0;
8009
+ var sign = 1;
8010
+ var expsign = 1;
8011
+
8012
+ var startIndex = this._currentIndex;
8013
+
8014
+ this._skipOptionalSpaces();
8015
+
8016
+ // Read the sign.
8017
+ if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "+")
8018
+ this._currentIndex++;
8019
+ else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "-") {
8020
+ this._currentIndex++;
8021
+ sign = -1;
8022
+ }
8023
+
8024
+ if (this._currentIndex == this._endIndex || ((this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9") && this._string.charAt(this._currentIndex) != "."))
8025
+ // The first character of a number must be one of [0-9+-.].
8026
+ return undefined;
8027
+
8028
+ // Read the integer part, build right-to-left.
8029
+ var startIntPartIndex = this._currentIndex;
8030
+ while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9")
8031
+ this._currentIndex++; // Advance to first non-digit.
8032
+
8033
+ if (this._currentIndex != startIntPartIndex) {
8034
+ var scanIntPartIndex = this._currentIndex - 1;
8035
+ var multiplier = 1;
8036
+ while (scanIntPartIndex >= startIntPartIndex) {
8037
+ integer += multiplier * (this._string.charAt(scanIntPartIndex--) - "0");
8038
+ multiplier *= 10;
8039
+ }
8040
+ }
8041
+
8042
+ // Read the decimals.
8043
+ if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ".") {
8044
+ this._currentIndex++;
8045
+
8046
+ // There must be a least one digit following the .
8047
+ if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9")
8048
+ return undefined;
8049
+ while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9")
8050
+ decimal += (this._string.charAt(this._currentIndex++) - "0") * (frac *= 0.1);
8051
+ }
8052
+
8053
+ // Read the exponent part.
8054
+ if (this._currentIndex != startIndex && this._currentIndex + 1 < this._endIndex && (this._string.charAt(this._currentIndex) == "e" || this._string.charAt(this._currentIndex) == "E") && (this._string.charAt(this._currentIndex + 1) != "x" && this._string.charAt(this._currentIndex + 1) != "m")) {
8055
+ this._currentIndex++;
8056
+
8057
+ // Read the sign of the exponent.
8058
+ if (this._string.charAt(this._currentIndex) == "+") {
8059
+ this._currentIndex++;
8060
+ } else if (this._string.charAt(this._currentIndex) == "-") {
8061
+ this._currentIndex++;
8062
+ expsign = -1;
8063
+ }
8064
+
8065
+ // There must be an exponent.
8066
+ if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9")
8067
+ return undefined;
8068
+
8069
+ while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9") {
8070
+ exponent *= 10;
8071
+ exponent += (this._string.charAt(this._currentIndex) - "0");
8072
+ this._currentIndex++;
8073
+ }
8074
+ }
8075
+
8076
+ var number = integer + decimal;
8077
+ number *= sign;
8078
+
8079
+ if (exponent)
8080
+ number *= Math.pow(10, expsign * exponent);
8081
+
8082
+ if (startIndex == this._currentIndex)
8083
+ return undefined;
8084
+
8085
+ this._skipOptionalSpacesOrDelimiter();
8086
+
8087
+ return number;
8088
+ }
8089
+
8090
+ Source.prototype._parseArcFlag = function() {
8091
+ if (this._currentIndex >= this._endIndex)
8092
+ return undefined;
8093
+ var flag = false;
8094
+ var flagChar = this._string.charAt(this._currentIndex++);
8095
+ if (flagChar == "0")
8096
+ flag = false;
8097
+ else if (flagChar == "1")
8098
+ flag = true;
8099
+ else
8100
+ return undefined;
8101
+
8102
+ this._skipOptionalSpacesOrDelimiter();
8103
+ return flag;
8104
+ }
8105
+
8106
+ Source.prototype.parseSegment = function() {
8107
+ var lookahead = this._string[this._currentIndex];
8108
+ var command = this._pathSegTypeFromChar(lookahead);
8109
+ if (command == SVGPathSeg.PATHSEG_UNKNOWN) {
8110
+ // Possibly an implicit command. Not allowed if this is the first command.
8111
+ if (this._previousCommand == SVGPathSeg.PATHSEG_UNKNOWN)
8112
+ return null;
8113
+ command = this._nextCommandHelper(lookahead, this._previousCommand);
8114
+ if (command == SVGPathSeg.PATHSEG_UNKNOWN)
8115
+ return null;
8116
+ } else {
8117
+ this._currentIndex++;
8118
+ }
8119
+
8120
+ this._previousCommand = command;
8121
+
8122
+ switch (command) {
8123
+ case SVGPathSeg.PATHSEG_MOVETO_REL:
8124
+ return new SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
8125
+ case SVGPathSeg.PATHSEG_MOVETO_ABS:
8126
+ return new SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
8127
+ case SVGPathSeg.PATHSEG_LINETO_REL:
8128
+ return new SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
8129
+ case SVGPathSeg.PATHSEG_LINETO_ABS:
8130
+ return new SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
8131
+ case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
8132
+ return new SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());
8133
+ case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
8134
+ return new SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());
8135
+ case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
8136
+ return new SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());
8137
+ case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
8138
+ return new SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());
8139
+ case SVGPathSeg.PATHSEG_CLOSEPATH:
8140
+ this._skipOptionalSpaces();
8141
+ return new SVGPathSegClosePath(owningPathSegList);
8142
+ case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
8143
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
8144
+ return new SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
8145
+ case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
8146
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
8147
+ return new SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
8148
+ case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
8149
+ var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
8150
+ return new SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2);
8151
+ case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
8152
+ var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
8153
+ return new SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2);
8154
+ case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
8155
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
8156
+ return new SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);
8157
+ case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
8158
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
8159
+ return new SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);
8160
+ case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
8161
+ return new SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());
8162
+ case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
8163
+ return new SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
8164
+ case SVGPathSeg.PATHSEG_ARC_REL:
8165
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
8166
+ return new SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
8167
+ case SVGPathSeg.PATHSEG_ARC_ABS:
8168
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
8169
+ return new SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
8170
+ default:
8171
+ throw "Unknown path seg type."
8172
+ }
8173
+ }
8174
+
8175
+ var builder = new Builder();
8176
+ var source = new Source(string);
8177
+
8178
+ if (!source.initialCommandIsMoveTo())
8179
+ return [];
8180
+ while (source.hasMoreData()) {
8181
+ var pathSeg = source.parseSegment();
8182
+ if (!pathSeg)
8183
+ return [];
8184
+ builder.appendSegment(pathSeg);
8185
+ }
8186
+
8187
+ return builder.pathSegList;
8188
+ }
8189
+ }
8190
+ }());
8191
+
8192
+ /* jshint ignore:end */
8193
+
7041
8194
  if (typeof define === 'function' && define.amd) {
7042
- define("c3", ["d3"], c3);
8195
+ define("c3", ["d3"], function () { return c3; });
7043
8196
  } else if ('undefined' !== typeof exports && 'undefined' !== typeof module) {
7044
8197
  module.exports = c3;
7045
8198
  } else {