highcharts-js-rails 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## v0.1.9 (2012-06-21) ##
2
+
3
+ * Update Highcharts to 2.2.5.
4
+
1
5
  ## v0.1.8 (2012-06-14) ##
2
6
 
3
7
  * Allow the additional assets to be easily accessible within a highcharts subdirectory.
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'highcharts-js-rails'
6
- s.version = '0.1.8'
6
+ s.version = '0.1.9'
7
7
  s.authors = ['Alex Robbin']
8
8
  s.email = ['agrobbin@gmail.com']
9
9
  s.homepage = 'https://github.com/agrobbin/highcharts-js-rails'
@@ -1,5 +1,5 @@
1
1
  /*
2
- Highcharts JS v2.2.4 (2012-05-31)
2
+ Highcharts JS v2.2.5 (2012-06-08)
3
3
 
4
4
  (c) 2009-2011 Torstein H?nsi
5
5
 
@@ -2,7 +2,7 @@
2
2
  // @compilation_level SIMPLE_OPTIMIZATIONS
3
3
 
4
4
  /**
5
- * @license Highcharts JS v2.2.4 (2012-05-31)
5
+ * @license Highcharts JS v2.2.5 (2012-06-08)
6
6
  *
7
7
  * (c) 2009-2011 Torstein Hønsi
8
8
  *
@@ -1103,7 +1103,10 @@ if (!globalAdapter && win.jQuery) {
1103
1103
  // Remove warnings in Chrome when accessing layerX and layerY. Although Highcharts
1104
1104
  // never uses these properties, Chrome includes them in the default click event and
1105
1105
  // raises the warning when they are copied over in the extend statement below.
1106
- if (eventArguments) {
1106
+ //
1107
+ // To avoid problems in IE (see #1010) where we cannot delete the properties and avoid
1108
+ // testing if they are there (warning in chrome) the only option is to test if running IE.
1109
+ if (!isIE && eventArguments) {
1107
1110
  delete eventArguments.layerX;
1108
1111
  delete eventArguments.layerY;
1109
1112
  }
@@ -1291,7 +1294,7 @@ defaultOptions = {
1291
1294
  },
1292
1295
  global: {
1293
1296
  useUTC: true,
1294
- canvasToolsURL: 'http://code.highcharts.com/2.2.4/modules/canvas-tools.js'
1297
+ canvasToolsURL: 'http://code.highcharts.com/2.2.5/modules/canvas-tools.js'
1295
1298
  },
1296
1299
  chart: {
1297
1300
  //animation: true,
@@ -2491,14 +2494,14 @@ SVGElement.prototype = {
2491
2494
  rad = rotation * deg2rad;
2492
2495
 
2493
2496
  // SVG elements
2494
- if (element.namespaceURI === SVG_NS) {
2497
+ if (element.namespaceURI === SVG_NS || wrapper.renderer.forExport) {
2495
2498
  try { // Fails in Firefox if the container has display: none.
2496
2499
 
2497
2500
  bBox = element.getBBox ?
2498
2501
  // SVG: use extend because IE9 is not allowed to change width and height in case
2499
2502
  // of rotation (below)
2500
2503
  extend({}, element.getBBox()) :
2501
- // Canvas renderer: // TODO: can this be removed now that we're checking for the SVG NS?
2504
+ // Canvas renderer and legacy IE in export mode
2502
2505
  {
2503
2506
  width: element.offsetWidth,
2504
2507
  height: element.offsetHeight
@@ -3891,7 +3894,8 @@ SVGRenderer.prototype = {
3891
3894
  x: x,
3892
3895
  y: y
3893
3896
  });
3894
- if (wrapper.symbolName) {
3897
+
3898
+ if (defined(anchorX)) {
3895
3899
  wrapper.attr({
3896
3900
  anchorX: anchorX,
3897
3901
  anchorY: anchorY
@@ -5162,6 +5166,12 @@ if (useCanVG) {
5162
5166
  // Empty constructor
5163
5167
  };
5164
5168
 
5169
+ /**
5170
+ * Start with an empty symbols object. This is needed when exporting is used (exporting.src.js will add a few symbols), but
5171
+ * the implementation from SvgRenderer will not be merged in until first render.
5172
+ */
5173
+ CanVGRenderer.prototype.symbols = {};
5174
+
5165
5175
  /**
5166
5176
  * Handles on demand download of canvg rendering support.
5167
5177
  */
@@ -6158,7 +6168,7 @@ Axis.prototype = {
6158
6168
  //axis.oldUserMin = UNDEFINED;
6159
6169
  //axis.oldUserMax = UNDEFINED;
6160
6170
  //axis.oldAxisLength = UNDEFINED;
6161
- axis.minRange = options.minRange || options.maxZoom;
6171
+ axis.minRange = axis.userMinRange = options.minRange || options.maxZoom;
6162
6172
  axis.range = options.range;
6163
6173
  axis.offset = options.offset || 0;
6164
6174
 
@@ -6872,7 +6882,7 @@ Axis.prototype = {
6872
6882
  }
6873
6883
 
6874
6884
  if (isLog) {
6875
- if (!secondPass && mathMin(axis.min, axis.dataMin) <= 0) {
6885
+ if (!secondPass && mathMin(axis.min, pick(axis.dataMin, axis.min)) <= 0) { // #978
6876
6886
  error(10, 1); // Can't plot negative values on log axis
6877
6887
  }
6878
6888
  axis.min = correctFloat(log2lin(axis.min)); // correctFloat cures #934
@@ -7926,7 +7936,7 @@ Tooltip.prototype = {
7926
7936
  // Now if the tooltip is below the chart, move it up. It's better to cover the
7927
7937
  // point than to disappear outside the chart. #834.
7928
7938
  if (y + boxHeight > plotTop + plotHeight) {
7929
- y = plotTop + plotHeight - boxHeight - distance; // below
7939
+ y = mathMax(plotTop, plotTop + plotHeight - boxHeight - distance); // below
7930
7940
  }
7931
7941
 
7932
7942
 
@@ -8006,7 +8016,8 @@ Tooltip.prototype = {
8006
8016
  });
8007
8017
 
8008
8018
  textConfig = {
8009
- x: point[0].category
8019
+ x: point[0].category,
8020
+ y: point[0].y
8010
8021
  };
8011
8022
  textConfig.points = pointConfig;
8012
8023
  point = point[0];
@@ -8301,9 +8312,17 @@ MouseTracker.prototype = {
8301
8312
  hoverPoint = chart.hoverPoint,
8302
8313
  tooltipPoints = chart.hoverPoints || hoverPoint,
8303
8314
  tooltip = chart.tooltip;
8315
+
8316
+ // Narrow in allowMove
8317
+ allowMove = allowMove && tooltip && tooltipPoints;
8318
+
8319
+ // Check if the points have moved outside the plot area, #1003
8320
+ if (allowMove && splat(tooltipPoints)[0].plotX === UNDEFINED) {
8321
+ allowMove = false;
8322
+ }
8304
8323
 
8305
8324
  // Just move the tooltip, #349
8306
- if (allowMove && tooltip && tooltipPoints) {
8325
+ if (allowMove) {
8307
8326
  tooltip.refresh(tooltipPoints);
8308
8327
 
8309
8328
  // Full reset
@@ -8915,7 +8934,7 @@ Legend.prototype = {
8915
8934
  legend.baseline,
8916
8935
  options.useHTML
8917
8936
  )
8918
- .css(item.visible ? itemStyle : itemHiddenStyle)
8937
+ .css(merge(item.visible ? itemStyle : itemHiddenStyle)) // merge to prevent modifying original (#1021)
8919
8938
  .attr({
8920
8939
  align: ltr ? 'left' : 'right',
8921
8940
  zIndex: 2
@@ -8931,17 +8950,22 @@ Legend.prototype = {
8931
8950
  li.css(item.visible ? itemStyle : itemHiddenStyle);
8932
8951
  item.setState();
8933
8952
  })
8934
- .on('click', function () {
8953
+ .on('click', function (event) {
8935
8954
  var strLegendItemClick = 'legendItemClick',
8936
8955
  fnLegendItemClick = function () {
8937
8956
  item.setVisible();
8938
8957
  };
8958
+
8959
+ // Pass over the click/touch event. #4.
8960
+ event = {
8961
+ browserEvent: event
8962
+ };
8939
8963
 
8940
8964
  // click the name or symbol
8941
8965
  if (item.firePointEvent) { // point
8942
- item.firePointEvent(strLegendItemClick, null, fnLegendItemClick);
8966
+ item.firePointEvent(strLegendItemClick, event, fnLegendItemClick);
8943
8967
  } else {
8944
- fireEvent(item, strLegendItemClick, null, fnLegendItemClick);
8968
+ fireEvent(item, strLegendItemClick, event, fnLegendItemClick);
8945
8969
  }
8946
8970
  });
8947
8971
 
@@ -9053,7 +9077,7 @@ Legend.prototype = {
9053
9077
  .add(legendGroup);
9054
9078
  legend.scrollGroup = renderer.g()
9055
9079
  .add(legend.contentGroup);
9056
- legend.clipRect = renderer.clipRect(0, 0, chart.chartWidth, chart.chartHeight);
9080
+ legend.clipRect = renderer.clipRect(0, 0, 9999, chart.chartHeight);
9057
9081
  legend.contentGroup.clip(legend.clipRect);
9058
9082
  }
9059
9083
 
@@ -9178,6 +9202,7 @@ Legend.prototype = {
9178
9202
  optionsY = options.y,
9179
9203
  alignTop = options.verticalAlign === 'top',
9180
9204
  spaceHeight = chart.spacingBox.height + (alignTop ? -optionsY : optionsY) - this.padding,
9205
+ maxHeight = options.maxHeight, // docs
9181
9206
  clipHeight,
9182
9207
  clipRect = this.clipRect,
9183
9208
  navOptions = options.navigation,
@@ -9185,9 +9210,13 @@ Legend.prototype = {
9185
9210
  arrowSize = navOptions.arrowSize || 12,
9186
9211
  nav = this.nav;
9187
9212
 
9213
+ // Adjust the height
9188
9214
  if (options.layout === 'horizontal') {
9189
9215
  spaceHeight /= 2;
9190
9216
  }
9217
+ if (maxHeight) {
9218
+ spaceHeight = mathMin(spaceHeight, maxHeight);
9219
+ }
9191
9220
 
9192
9221
  // Reset the legend height and adjust the clipping rectangle
9193
9222
  if (legendHeight > spaceHeight) {
@@ -9849,7 +9878,7 @@ Chart.prototype = {
9849
9878
  });
9850
9879
  }
9851
9880
 
9852
- if (newMin > mathMin(extremes.dataMin, extremes.min) && newMax < mathMax(extremes.dataMax, extremes.max)) {
9881
+ if (xAxis.series.length && newMin > mathMin(extremes.dataMin, extremes.min) && newMax < mathMax(extremes.dataMax, extremes.max)) {
9853
9882
  xAxis.setExtremes(newMin, newMax, true, false);
9854
9883
  }
9855
9884
 
@@ -10195,9 +10224,8 @@ Chart.prototype = {
10195
10224
  var chart = this,
10196
10225
  chartWidth,
10197
10226
  chartHeight,
10198
- spacingBox = chart.spacingBox;
10199
-
10200
- var chartTitle = chart.title,
10227
+ spacingBox,
10228
+ chartTitle = chart.title,
10201
10229
  chartSubtitle = chart.subtitle;
10202
10230
 
10203
10231
  chart.isResizing += 1;
@@ -10242,6 +10270,7 @@ Chart.prototype = {
10242
10270
  chart.getMargins();
10243
10271
 
10244
10272
  // move titles
10273
+ spacingBox = chart.spacingBox;
10245
10274
  if (chartTitle) {
10246
10275
  chartTitle.align(null, null, spacingBox);
10247
10276
  }
@@ -10649,7 +10678,7 @@ Chart.prototype = {
10649
10678
  /*jslint eqeq: false*/
10650
10679
  if (useCanVG) {
10651
10680
  // Delay rendering until canvg library is downloaded and ready
10652
- CanVGController.push(chart.firstRender, options.global.canvasToolsURL);
10681
+ CanVGController.push(function () { chart.firstRender(); }, options.global.canvasToolsURL);
10653
10682
  } else {
10654
10683
  doc.attachEvent(ONREADYSTATECHANGE, function () {
10655
10684
  doc.detachEvent(ONREADYSTATECHANGE, chart.firstRender);
@@ -11018,9 +11047,24 @@ Point.prototype = {
11018
11047
  obj,
11019
11048
  key,
11020
11049
  replacement,
11050
+ repOptionKey,
11021
11051
  parts,
11022
11052
  prop,
11023
- i;
11053
+ i,
11054
+ cfg = { // docs: percentageDecimals, percentagePrefix, percentageSuffix, totalDecimals, totalPrefix, totalSuffix
11055
+ y: 0, // 0: use 'value' for repOptionKey
11056
+ open: 0,
11057
+ high: 0,
11058
+ low: 0,
11059
+ close: 0,
11060
+ percentage: 1, // 1: use the self name for repOptionKey
11061
+ total: 1
11062
+ };
11063
+
11064
+ // Backwards compatibility to y naming in early Highstock
11065
+ seriesTooltipOptions.valuePrefix = seriesTooltipOptions.valuePrefix || seriesTooltipOptions.yPrefix;
11066
+ seriesTooltipOptions.valueDecimals = seriesTooltipOptions.valueDecimals || seriesTooltipOptions.yDecimals;
11067
+ seriesTooltipOptions.valueSuffix = seriesTooltipOptions.valueSuffix || seriesTooltipOptions.ySuffix;
11024
11068
 
11025
11069
  // loop over the variables defined on the form {series.name}, {point.y} etc
11026
11070
  for (i in match) {
@@ -11033,11 +11077,11 @@ Point.prototype = {
11033
11077
  prop = parts[2];
11034
11078
 
11035
11079
  // Add some preformatting
11036
- if (obj === point && (prop === 'y' || prop === 'open' || prop === 'high' ||
11037
- prop === 'low' || prop === 'close')) {
11038
- replacement = (seriesTooltipOptions.valuePrefix || seriesTooltipOptions.yPrefix || '') +
11039
- numberFormat(point[prop], pick(seriesTooltipOptions.valueDecimals, seriesTooltipOptions.yDecimals, -1)) +
11040
- (seriesTooltipOptions.valueSuffix || seriesTooltipOptions.ySuffix || '');
11080
+ if (obj === point && cfg.hasOwnProperty(prop)) {
11081
+ repOptionKey = cfg[prop] ? prop : 'value';
11082
+ replacement = (seriesTooltipOptions[repOptionKey + 'Prefix'] || '') +
11083
+ numberFormat(point[prop], pick(seriesTooltipOptions[repOptionKey + 'Decimals'], -1)) +
11084
+ (seriesTooltipOptions[repOptionKey + 'Suffix'] || '');
11041
11085
 
11042
11086
  // Automatic replacement
11043
11087
  } else {
@@ -11249,7 +11293,7 @@ Point.prototype = {
11249
11293
  } else {
11250
11294
  // if a graphic is not applied to each point in the normal state, create a shared
11251
11295
  // graphic for the hover state
11252
- if (state) {
11296
+ if (state && markerStateOptions) {
11253
11297
  if (!stateMarkerGraphic) {
11254
11298
  radius = markerStateOptions.radius;
11255
11299
  series.stateMarkerGraphic = stateMarkerGraphic = chart.renderer.symbol(
@@ -11499,9 +11543,11 @@ Series.prototype = {
11499
11543
  * Get the series' color
11500
11544
  */
11501
11545
  getColor: function () {
11502
- var defaultColors = this.chart.options.colors,
11546
+ var options = this.options,
11547
+ defaultColors = this.chart.options.colors,
11503
11548
  counters = this.chart.counters;
11504
- this.color = this.options.color || defaultColors[counters.color++] || '#0000ff';
11549
+ this.color = options.color ||
11550
+ (!options.colorByPoint && defaultColors[counters.color++]) || 'gray';
11505
11551
  counters.wrapColor(defaultColors.length);
11506
11552
  },
11507
11553
  /**
@@ -11742,7 +11788,7 @@ Series.prototype = {
11742
11788
 
11743
11789
  // reset minRange (#878)
11744
11790
  if (xAxis) {
11745
- xAxis.minRange = UNDEFINED;
11791
+ xAxis.minRange = xAxis.userMinRange;
11746
11792
  }
11747
11793
 
11748
11794
  // redraw
@@ -11903,7 +11949,7 @@ Series.prototype = {
11903
11949
  if (!hasGroupedData) {
11904
11950
  if (data[cursor]) {
11905
11951
  point = data[cursor];
11906
- } else {
11952
+ } else if (dataOptions[cursor] !== UNDEFINED) { // #970
11907
11953
  data[cursor] = point = (new pointClass()).init(series, dataOptions[cursor], processedXData[i]);
11908
11954
  }
11909
11955
  points[i] = point;
@@ -11922,6 +11968,7 @@ Series.prototype = {
11922
11968
  }
11923
11969
  if (data[i]) {
11924
11970
  data[i].destroyElements();
11971
+ data[i].plotX = UNDEFINED; // #1003
11925
11972
  }
11926
11973
  }
11927
11974
  }
@@ -12071,7 +12118,7 @@ Series.prototype = {
12071
12118
  point = points[i];
12072
12119
  low = points[i - 1] ? points[i - 1]._high + 1 : 0;
12073
12120
  point._high = high = points[i + 1] ?
12074
- (mathFloor((point.plotX + (points[i + 1] ? points[i + 1].plotX : plotSize)) / 2)) :
12121
+ mathMax(0, mathFloor((point.plotX + (points[i + 1] ? points[i + 1].plotX : plotSize)) / 2)) :
12075
12122
  plotSize;
12076
12123
 
12077
12124
  while (low >= 0 && low <= high) {
@@ -12769,7 +12816,7 @@ Series.prototype = {
12769
12816
  graph.animate({ d: graphPath });
12770
12817
 
12771
12818
  } else {
12772
- if (lineWidth || options.states.hover.lineWidth) { // #940
12819
+ if (lineWidth) {
12773
12820
  attribs = {
12774
12821
  stroke: color,
12775
12822
  'stroke-width': lineWidth
@@ -12824,14 +12871,11 @@ Series.prototype = {
12824
12871
  /**
12825
12872
  * Create the series group
12826
12873
  */
12827
- createGroup: function (doClip) {
12874
+ createGroup: function () {
12828
12875
 
12829
12876
  var chart = this.chart,
12830
12877
  group = this.group = chart.renderer.g('series');
12831
12878
 
12832
- if (doClip) {
12833
- group.clip(this.clipRect);
12834
- }
12835
12879
  group.attr({
12836
12880
  visibility: this.visible ? VISIBLE : HIDDEN,
12837
12881
  zIndex: this.options.zIndex
@@ -12876,20 +12920,10 @@ Series.prototype = {
12876
12920
 
12877
12921
 
12878
12922
  // the group
12879
- series.createGroup(doClip);
12880
- if (!series.group) {
12881
- group = series.group = renderer.g('series');
12882
-
12883
- group.attr({
12884
- visibility: series.visible ? VISIBLE : HIDDEN,
12885
- zIndex: options.zIndex
12886
- })
12887
- .translate(series.xAxis.left, series.yAxis.top)
12888
- .add(chart.seriesGroup);
12889
- } else {
12890
- group = series.group;
12891
- }
12892
-
12923
+ series.createGroup();
12924
+ group = series.group;
12925
+
12926
+
12893
12927
  series.drawDataLabels();
12894
12928
 
12895
12929
  // initiate the animation
@@ -13560,7 +13594,7 @@ var ColumnSeries = extendClass(Series, {
13560
13594
  // the number of column series in the plot, the groupPadding
13561
13595
  // and the pointPadding options
13562
13596
  var points = series.points,
13563
- categoryWidth = mathAbs(xAxis.transA) * (xAxis.ordinalSlope || xAxis.closestPointRange || 1),
13597
+ categoryWidth = mathAbs(xAxis.transA) * (xAxis.ordinalSlope || options.pointRange || xAxis.closestPointRange || 1),
13564
13598
  groupPadding = categoryWidth * options.groupPadding,
13565
13599
  groupWidth = categoryWidth - 2 * groupPadding,
13566
13600
  pointOffsetWidth = groupWidth / columnCount,
@@ -14642,6 +14676,6 @@ extend(Highcharts, {
14642
14676
  extendClass: extendClass,
14643
14677
  pInt: pInt,
14644
14678
  product: 'Highcharts',
14645
- version: '2.2.4'
14679
+ version: '2.2.5'
14646
14680
  });
14647
14681
  }());
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v2.2.4 (2012-05-31)
2
+ * @license Highcharts JS v2.2.5 (2012-06-08)
3
3
  * MooTools adapter
4
4
  *
5
5
  * (c) 2010-2011 Torstein Hønsi
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v2.2.4 (2012-05-31)
2
+ * @license Highcharts JS v2.2.5 (2012-06-08)
3
3
  * Prototype adapter
4
4
  *
5
5
  * @author Michael Nelson, Torstein Hønsi.
@@ -2908,7 +2908,7 @@ if (CanvasRenderingContext2D) {
2908
2908
  });
2909
2909
  }
2910
2910
  }/**
2911
- * @license Highcharts JS v2.2.4 (2012-05-31)
2911
+ * @license Highcharts JS v2.2.5 (2012-06-08)
2912
2912
  * CanVGRenderer Extension module
2913
2913
  *
2914
2914
  * (c) 2011-2012 Torstein Hønsi, Erik Olsson
@@ -2933,7 +2933,6 @@ if (CanvasRenderingContext2D) {
2933
2933
  extend = Highcharts.extend,
2934
2934
  merge = Highcharts.merge,
2935
2935
  addEvent = Highcharts.addEvent,
2936
- placeBox = Highcharts.placeBox,
2937
2936
  createElement = Highcharts.createElement,
2938
2937
  discardElement = Highcharts.discardElement;
2939
2938
 
@@ -3034,7 +3033,7 @@ if (CanvasRenderingContext2D) {
3034
3033
  tooltipDiv.innerHTML = args.text;
3035
3034
 
3036
3035
  // Compute the best position for the tooltip based on the divs size and container size.
3037
- position = placeBox(tooltipDiv.offsetWidth, tooltipDiv.offsetHeight, offsetLeft, offsetTop, chartContainer.offsetWidth, chartContainer.offsetHeight, {x: args.x, y: args.y}, 12);
3036
+ position = chart.tooltip.getPosition(tooltipDiv.offsetWidth, tooltipDiv.offsetHeight, {plotX: args.x, plotY: args.y});
3038
3037
 
3039
3038
  css(tooltipDiv, {
3040
3039
  visibility: VISIBLE,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v2.2.4 (2012-05-31)
2
+ * @license Highcharts JS v2.2.5 (2012-06-08)
3
3
  * Exporting module
4
4
  *
5
5
  * (c) 2010-2011 Torstein Hønsi
@@ -192,11 +192,7 @@ extend(Chart.prototype, {
192
192
  if (!doc.createElementNS) {
193
193
  /*jslint unparam: true*//* allow unused parameter ns in function below */
194
194
  doc.createElementNS = function (ns, tagName) {
195
- var elem = doc.createElement(tagName);
196
- elem.getBBox = function () {
197
- return HC.Renderer.prototype.Element.prototype.getBBox.apply({ element: elem });
198
- };
199
- return elem;
195
+ return doc.createElement(tagName);
200
196
  };
201
197
  /*jslint unparam: false*/
202
198
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: highcharts-js-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-14 00:00:00.000000000 Z
12
+ date: 2012-06-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties