corrade-nucleus-nucleons – Diff between revs 1 and 11

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 1 Rev 11
1 /** 1 /**
2 * @license Highcharts JS v5.0.10 (2017-03-31) 2 * @license Highcharts JS v5.0.12 (2017-05-24)
3 * Gantt series 3 * Gantt series
4 * 4 *
5 * (c) 2016 Lars A. V. Cabrera 5 * (c) 2016 Lars A. V. Cabrera
6 * 6 *
7 * --- WORK IN PROGRESS --- 7 * --- WORK IN PROGRESS ---
8 * 8 *
9 * License: www.highcharts.com/license 9 * License: www.highcharts.com/license
10 */ 10 */
11 'use strict'; 11 'use strict';
12 (function(factory) { 12 (function(factory) {
13 if (typeof module === 'object' && module.exports) { 13 if (typeof module === 'object' && module.exports) {
14 module.exports = factory; 14 module.exports = factory;
15 } else { 15 } else {
16 factory(Highcharts); 16 factory(Highcharts);
17 } 17 }
18 }(function(Highcharts) { 18 }(function(Highcharts) {
19 (function(H) { 19 (function(H) {
20 /** 20 /**
21 * (c) 2016 Highsoft AS 21 * (c) 2016 Highsoft AS
22 * Authors: Lars A. V. Cabrera 22 * Authors: Lars A. V. Cabrera
23 * 23 *
24 * License: www.highcharts.com/license 24 * License: www.highcharts.com/license
25 */ 25 */
26   26  
27 var dateFormat = H.dateFormat, 27 var dateFormat = H.dateFormat,
28 each = H.each, 28 each = H.each,
29 isObject = H.isObject, 29 isObject = H.isObject,
30 pick = H.pick, 30 pick = H.pick,
31 wrap = H.wrap, 31 wrap = H.wrap,
32 Axis = H.Axis, 32 Axis = H.Axis,
33 Chart = H.Chart, 33 Chart = H.Chart,
34 Tick = H.Tick; 34 Tick = H.Tick;
35   35  
36   36  
37 // Enum for which side the axis is on. 37 // Enum for which side the axis is on.
38 // Maps to axis.side 38 // Maps to axis.side
39 var axisSide = { 39 var axisSide = {
40 top: 0, 40 top: 0,
41 right: 1, 41 right: 1,
42 bottom: 2, 42 bottom: 2,
43 left: 3, 43 left: 3,
44 0: 'top', 44 0: 'top',
45 1: 'right', 45 1: 'right',
46 2: 'bottom', 46 2: 'bottom',
47 3: 'left' 47 3: 'left'
48 }; 48 };
49   49  
50 /** 50 /**
51 * Checks if an axis is the outer axis in its dimension. Since 51 * Checks if an axis is the outer axis in its dimension. Since
52 * axes are placed outwards in order, the axis with the highest 52 * axes are placed outwards in order, the axis with the highest
53 * index is the outermost axis. 53 * index is the outermost axis.
54 * 54 *
55 * Example: If there are multiple x-axes at the top of the chart, 55 * Example: If there are multiple x-axes at the top of the chart,
56 * this function returns true if the axis supplied is the last 56 * this function returns true if the axis supplied is the last
57 * of the x-axes. 57 * of the x-axes.
58 * 58 *
59 * @return true if the axis is the outermost axis in its dimension; 59 * @return true if the axis is the outermost axis in its dimension;
60 * false if not 60 * false if not
61 */ 61 */
62 Axis.prototype.isOuterAxis = function() { 62 Axis.prototype.isOuterAxis = function() {
63 var axis = this, 63 var axis = this,
64 thisIndex = -1, 64 thisIndex = -1,
65 isOuter = true; 65 isOuter = true;
66   66  
67 each(this.chart.axes, function(otherAxis, index) { 67 each(this.chart.axes, function(otherAxis, index) {
68 if (otherAxis.side === axis.side) { 68 if (otherAxis.side === axis.side) {
69 if (otherAxis === axis) { 69 if (otherAxis === axis) {
70 // Get the index of the axis in question 70 // Get the index of the axis in question
71 thisIndex = index; 71 thisIndex = index;
72   72  
73 // Check thisIndex >= 0 in case thisIndex has 73 // Check thisIndex >= 0 in case thisIndex has
74 // not been found yet 74 // not been found yet
75 } else if (thisIndex >= 0 && index > thisIndex) { 75 } else if (thisIndex >= 0 && index > thisIndex) {
76 // There was an axis on the same side with a 76 // There was an axis on the same side with a
77 // higher index. Exit the loop. 77 // higher index. Exit the loop.
78 isOuter = false; 78 isOuter = false;
79 return; 79 return;
80 } 80 }
81 } 81 }
82 }); 82 });
83 // There were either no other axes on the same side, 83 // There were either no other axes on the same side,
84 // or the other axes were not farther from the chart 84 // or the other axes were not farther from the chart
85 return isOuter; 85 return isOuter;
86 }; 86 };
87   87  
88 /** 88 /**
89 * Shortcut function to Tick.label.getBBox().width. 89 * Shortcut function to Tick.label.getBBox().width.
90 * 90 *
91 * @return {number} width - the width of the tick label 91 * @return {number} width - the width of the tick label
92 */ 92 */
93 Tick.prototype.getLabelWidth = function() { 93 Tick.prototype.getLabelWidth = function() {
94 return this.label.getBBox().width; 94 return this.label.getBBox().width;
95 }; 95 };
96   96  
97 /** 97 /**
98 * Get the maximum label length. 98 * Get the maximum label length.
99 * This function can be used in states where the axis.maxLabelLength has not 99 * This function can be used in states where the axis.maxLabelLength has not
100 * been set. 100 * been set.
101 * 101 *
102 * @param {boolean} force - Optional parameter to force a new calculation, even 102 * @param {boolean} force - Optional parameter to force a new calculation, even
103 * if a value has already been set 103 * if a value has already been set
104 * @return {number} maxLabelLength - the maximum label length of the axis 104 * @return {number} maxLabelLength - the maximum label length of the axis
105 */ 105 */
106 Axis.prototype.getMaxLabelLength = function(force) { 106 Axis.prototype.getMaxLabelLength = function(force) {
107 var tickPositions = this.tickPositions, 107 var tickPositions = this.tickPositions,
108 ticks = this.ticks, 108 ticks = this.ticks,
109 maxLabelLength = 0; 109 maxLabelLength = 0;
110   110  
111 if (!this.maxLabelLength || force) { 111 if (!this.maxLabelLength || force) {
112 each(tickPositions, function(tick) { 112 each(tickPositions, function(tick) {
113 tick = ticks[tick]; 113 tick = ticks[tick];
114 if (tick && tick.labelLength > maxLabelLength) { 114 if (tick && tick.labelLength > maxLabelLength) {
115 maxLabelLength = tick.labelLength; 115 maxLabelLength = tick.labelLength;
116 } 116 }
117 }); 117 });
118 this.maxLabelLength = maxLabelLength; 118 this.maxLabelLength = maxLabelLength;
119 } 119 }
120 return this.maxLabelLength; 120 return this.maxLabelLength;
121 }; 121 };
122   122  
123 /** 123 /**
124 * Adds the axis defined in axis.options.title 124 * Adds the axis defined in axis.options.title
125 */ 125 */
126 Axis.prototype.addTitle = function() { 126 Axis.prototype.addTitle = function() {
127 var axis = this, 127 var axis = this,
128 renderer = axis.chart.renderer, 128 renderer = axis.chart.renderer,
129 axisParent = axis.axisParent, 129 axisParent = axis.axisParent,
130 horiz = axis.horiz, 130 horiz = axis.horiz,
131 opposite = axis.opposite, 131 opposite = axis.opposite,
132 options = axis.options, 132 options = axis.options,
133 axisTitleOptions = options.title, 133 axisTitleOptions = options.title,
134 hasData, 134 hasData,
135 showAxis, 135 showAxis,
136 textAlign; 136 textAlign;
137   137  
138 // For reuse in Axis.render 138 // For reuse in Axis.render
139 hasData = axis.hasData(); 139 hasData = axis.hasData();
140 axis.showAxis = showAxis = hasData || pick(options.showEmpty, true); 140 axis.showAxis = showAxis = hasData || pick(options.showEmpty, true);
141   141  
142 // Disregard title generation in original Axis.getOffset() 142 // Disregard title generation in original Axis.getOffset()
143 options.title = ''; 143 options.title = '';
144   144  
145 if (!axis.axisTitle) { 145 if (!axis.axisTitle) {
146 textAlign = axisTitleOptions.textAlign; 146 textAlign = axisTitleOptions.textAlign;
147 if (!textAlign) { 147 if (!textAlign) {
148 textAlign = (horiz ? { 148 textAlign = (horiz ? {
149 low: 'left', 149 low: 'left',
150 middle: 'center', 150 middle: 'center',
151 high: 'right' 151 high: 'right'
152 } : { 152 } : {
153 low: opposite ? 'right' : 'left', 153 low: opposite ? 'right' : 'left',
154 middle: 'center', 154 middle: 'center',
155 high: opposite ? 'left' : 'right' 155 high: opposite ? 'left' : 'right'
156 })[axisTitleOptions.align]; 156 })[axisTitleOptions.align];
157 } 157 }
158 axis.axisTitle = renderer.text( 158 axis.axisTitle = renderer.text(
159 axisTitleOptions.text, 159 axisTitleOptions.text,
160 0, 160 0,
161 0, 161 0,
162 axisTitleOptions.useHTML 162 axisTitleOptions.useHTML
163 ) 163 )
164 .attr({ 164 .attr({
165 zIndex: 7, 165 zIndex: 7,
166 rotation: axisTitleOptions.rotation || 0, 166 rotation: axisTitleOptions.rotation || 0,
167 align: textAlign 167 align: textAlign
168 }) 168 })
169 .addClass('highcharts-axis-title') 169 .addClass('highcharts-axis-title')
170   170  
171 // Add to axisParent instead of axisGroup, to ignore the space 171 // Add to axisParent instead of axisGroup, to ignore the space
172 // it takes 172 // it takes
173 .add(axisParent); 173 .add(axisParent);
174 axis.axisTitle.isNew = true; 174 axis.axisTitle.isNew = true;
175 } 175 }
176   176  
177   177  
178 // hide or show the title depending on whether showEmpty is set 178 // hide or show the title depending on whether showEmpty is set
179 axis.axisTitle[showAxis ? 'show' : 'hide'](true); 179 axis.axisTitle[showAxis ? 'show' : 'hide'](true);
180 }; 180 };
181   181  
182 /** 182 /**
183 * Add custom date formats 183 * Add custom date formats
184 */ 184 */
185 H.dateFormats = { 185 H.dateFormats = {
186 // Week number 186 // Week number
187 W: function(timestamp) { 187 W: function(timestamp) {
188 var date = new Date(timestamp), 188 var date = new Date(timestamp),
189 day = date.getUTCDay() === 0 ? 7 : date.getUTCDay(), 189 day = date.getUTCDay() === 0 ? 7 : date.getUTCDay(),
190 time = date.getTime(), 190 time = date.getTime(),
191 startOfYear = new Date(date.getUTCFullYear(), 0, 1, -6), 191 startOfYear = new Date(date.getUTCFullYear(), 0, 1, -6),
192 dayNumber; 192 dayNumber;
193 date.setDate(date.getUTCDate() + 4 - day); 193 date.setDate(date.getUTCDate() + 4 - day);
194 dayNumber = Math.floor((time - startOfYear) / 86400000); 194 dayNumber = Math.floor((time - startOfYear) / 86400000);
195 return 1 + Math.floor(dayNumber / 7); 195 return 1 + Math.floor(dayNumber / 7);
196 }, 196 },
197 // First letter of the day of the week, e.g. 'M' for 'Monday'. 197 // First letter of the day of the week, e.g. 'M' for 'Monday'.
198 E: function(timestamp) { 198 E: function(timestamp) {
199 return dateFormat('%a', timestamp, true).charAt(0); 199 return dateFormat('%a', timestamp, true).charAt(0);
200 } 200 }
201 }; 201 };
202   202  
203 /** 203 /**
204 * Prevents adding the last tick label if the axis is not a category axis. 204 * Prevents adding the last tick label if the axis is not a category axis.
205 * 205 *
206 * Since numeric labels are normally placed at starts and ends of a range of 206 * Since numeric labels are normally placed at starts and ends of a range of
207 * value, and this module makes the label point at the value, an "extra" label 207 * value, and this module makes the label point at the value, an "extra" label
208 * would appear. 208 * would appear.
209 * 209 *
210 * @param {function} proceed - the original function 210 * @param {function} proceed - the original function
211 */ 211 */
212 wrap(Tick.prototype, 'addLabel', function(proceed) { 212 wrap(Tick.prototype, 'addLabel', function(proceed) {
213 var axis = this.axis, 213 var axis = this.axis,
214 isCategoryAxis = axis.options.categories !== undefined, 214 isCategoryAxis = axis.options.categories !== undefined,
215 tickPositions = axis.tickPositions, 215 tickPositions = axis.tickPositions,
216 lastTick = tickPositions[tickPositions.length - 1], 216 lastTick = tickPositions[tickPositions.length - 1],
217 isLastTick = this.pos !== lastTick; 217 isLastTick = this.pos !== lastTick;
218   218  
219 if (!axis.options.grid || isCategoryAxis || isLastTick) { 219 if (!axis.options.grid || isCategoryAxis || isLastTick) {
220 proceed.apply(this); 220 proceed.apply(this);
221 } 221 }
222 }); 222 });
223   223  
224 /** 224 /**
225 * Center tick labels vertically and horizontally between ticks 225 * Center tick labels vertically and horizontally between ticks
226 * 226 *
227 * @param {function} proceed - the original function 227 * @param {function} proceed - the original function
228 * 228 *
229 * @return {object} object - an object containing x and y positions 229 * @return {object} object - an object containing x and y positions
230 * for the tick 230 * for the tick
231 */ 231 */
232 wrap(Tick.prototype, 'getLabelPosition', function(proceed, x, y, label) { 232 wrap(Tick.prototype, 'getLabelPosition', function(proceed, x, y, label) {
233 var retVal = proceed.apply(this, Array.prototype.slice.call(arguments, 1)), 233 var retVal = proceed.apply(this, Array.prototype.slice.call(arguments, 1)),
234 axis = this.axis, 234 axis = this.axis,
235 options = axis.options, 235 options = axis.options,
236 tickInterval = options.tickInterval || 1, 236 tickInterval = options.tickInterval || 1,
237 newX, 237 newX,
238 newPos, 238 newPos,
239 axisHeight, 239 axisHeight,
240 fontSize, 240 fontSize,
241 labelMetrics, 241 labelMetrics,
242 lblB, 242 lblB,
243 lblH, 243 lblH,
244 labelCenter; 244 labelCenter;
245   245  
246 // Only center tick labels if axis has option grid: true 246 // Only center tick labels if axis has option grid: true
247 if (options.grid) { 247 if (options.grid) {
248 fontSize = options.labels.style.fontSize; 248 fontSize = options.labels.style.fontSize;
249 labelMetrics = axis.chart.renderer.fontMetrics(fontSize, label); 249 labelMetrics = axis.chart.renderer.fontMetrics(fontSize, label);
250 lblB = labelMetrics.b; 250 lblB = labelMetrics.b;
251 lblH = labelMetrics.h; 251 lblH = labelMetrics.h;
252   252  
253 if (axis.horiz && options.categories === undefined) { 253 if (axis.horiz && options.categories === undefined) {
254 // Center x position 254 // Center x position
255 axisHeight = axis.axisGroup.getBBox().height; 255 axisHeight = axis.axisGroup.getBBox().height;
256 newPos = this.pos + tickInterval / 2; 256 newPos = this.pos + tickInterval / 2;
257 retVal.x = axis.translate(newPos) + axis.left; 257 retVal.x = axis.translate(newPos) + axis.left;
258 labelCenter = (axisHeight / 2) + (lblH / 2) - Math.abs(lblH - lblB); 258 labelCenter = (axisHeight / 2) + (lblH / 2) - Math.abs(lblH - lblB);
259   259  
260 // Center y position 260 // Center y position
261 if (axis.side === axisSide.top) { 261 if (axis.side === axisSide.top) {
262 retVal.y = y - labelCenter; 262 retVal.y = y - labelCenter;
263 } else { 263 } else {
264 retVal.y = y + labelCenter; 264 retVal.y = y + labelCenter;
265 } 265 }
266 } else { 266 } else {
267 // Center y position 267 // Center y position
268 if (options.categories === undefined) { 268 if (options.categories === undefined) {
269 newPos = this.pos + (tickInterval / 2); 269 newPos = this.pos + (tickInterval / 2);
270 retVal.y = axis.translate(newPos) + axis.top + (lblB / 2); 270 retVal.y = axis.translate(newPos) + axis.top + (lblB / 2);
271 } 271 }
272   272  
273 // Center x position 273 // Center x position
274 newX = (this.getLabelWidth() / 2) - (axis.maxLabelLength / 2); 274 newX = (this.getLabelWidth() / 2) - (axis.maxLabelLength / 2);
275 if (axis.side === axisSide.left) { 275 if (axis.side === axisSide.left) {
276 retVal.x += newX; 276 retVal.x += newX;
277 } else { 277 } else {
278 retVal.x -= newX; 278 retVal.x -= newX;
279 } 279 }
280 } 280 }
281 } 281 }
282 return retVal; 282 return retVal;
283 }); 283 });
284   284  
285   285  
286 /** 286 /**
287 * Draw vertical ticks extra long to create cell floors and roofs. 287 * Draw vertical ticks extra long to create cell floors and roofs.
288 * Overrides the tickLength for vertical axes. 288 * Overrides the tickLength for vertical axes.
289 * 289 *
290 * @param {function} proceed - the original function 290 * @param {function} proceed - the original function
291 * @returns {array} retVal - 291 * @returns {array} retVal -
292 */ 292 */
293 wrap(Axis.prototype, 'tickSize', function(proceed) { 293 wrap(Axis.prototype, 'tickSize', function(proceed) {
294 var axis = this, 294 var axis = this,
295 retVal = proceed.apply(axis, Array.prototype.slice.call(arguments, 1)), 295 retVal = proceed.apply(axis, Array.prototype.slice.call(arguments, 1)),
296 labelPadding, 296 labelPadding,
297 distance; 297 distance;
298   298  
299 if (axis.options.grid && !axis.horiz) { 299 if (axis.options.grid && !axis.horiz) {
300 labelPadding = (Math.abs(axis.defaultLeftAxisOptions.labels.x) * 2); 300 labelPadding = (Math.abs(axis.defaultLeftAxisOptions.labels.x) * 2);
301 if (!axis.maxLabelLength) { 301 if (!axis.maxLabelLength) {
302 axis.maxLabelLength = axis.getMaxLabelLength(); 302 axis.maxLabelLength = axis.getMaxLabelLength();
303 } 303 }
304 distance = axis.maxLabelLength + labelPadding; 304 distance = axis.maxLabelLength + labelPadding;
305   305  
306 retVal[0] = distance; 306 retVal[0] = distance;
307 } 307 }
308 return retVal; 308 return retVal;
309 }); 309 });
310   310  
311 /** 311 /**
312 * Disregards space required by axisTitle, by adding axisTitle to axisParent 312 * Disregards space required by axisTitle, by adding axisTitle to axisParent
313 * instead of axisGroup, and disregarding margins and offsets related to 313 * instead of axisGroup, and disregarding margins and offsets related to
314 * axisTitle. 314 * axisTitle.
315 * 315 *
316 * @param {function} proceed - the original function 316 * @param {function} proceed - the original function
317 */ 317 */
318 wrap(Axis.prototype, 'getOffset', function(proceed) { 318 wrap(Axis.prototype, 'getOffset', function(proceed) {
319 var axis = this, 319 var axis = this,
320 axisOffset = axis.chart.axisOffset, 320 axisOffset = axis.chart.axisOffset,
321 side = axis.side, 321 side = axis.side,
322 axisHeight, 322 axisHeight,
323 tickSize, 323 tickSize,
324 options = axis.options, 324 options = axis.options,
325 axisTitleOptions = options.title, 325 axisTitleOptions = options.title,
326 addTitle = axisTitleOptions && 326 addTitle = axisTitleOptions &&
327 axisTitleOptions.text && 327 axisTitleOptions.text &&
328 axisTitleOptions.enabled !== false; 328 axisTitleOptions.enabled !== false;
329   329  
330 if (axis.options.grid && isObject(axis.options.title)) { 330 if (axis.options.grid && isObject(axis.options.title)) {
331   331  
332 tickSize = axis.tickSize('tick')[0]; 332 tickSize = axis.tickSize('tick')[0];
333 if (axisOffset[side] && tickSize) { 333 if (axisOffset[side] && tickSize) {
334 axisHeight = axisOffset[side] + tickSize; 334 axisHeight = axisOffset[side] + tickSize;
335 } 335 }
336   336  
337 if (addTitle) { 337 if (addTitle) {
338 // Use the custom addTitle() to add it, while preventing making room 338 // Use the custom addTitle() to add it, while preventing making room
339 // for it 339 // for it
340 axis.addTitle(); 340 axis.addTitle();
341 } 341 }
342   342  
343 proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); 343 proceed.apply(axis, Array.prototype.slice.call(arguments, 1));
344   344  
345 axisOffset[side] = pick(axisHeight, axisOffset[side]); 345 axisOffset[side] = pick(axisHeight, axisOffset[side]);
346   346  
347   347  
348 // Put axis options back after original Axis.getOffset() has been called 348 // Put axis options back after original Axis.getOffset() has been called
349 options.title = axisTitleOptions; 349 options.title = axisTitleOptions;
350   350  
351 } else { 351 } else {
352 proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); 352 proceed.apply(axis, Array.prototype.slice.call(arguments, 1));
353 } 353 }
354 }); 354 });
355   355  
356 /** 356 /**
357 * Prevents rotation of labels when squished, as rotating them would not 357 * Prevents rotation of labels when squished, as rotating them would not
358 * help. 358 * help.
359 * 359 *
360 * @param {function} proceed - the original function 360 * @param {function} proceed - the original function
361 */ 361 */
362 wrap(Axis.prototype, 'renderUnsquish', function(proceed) { 362 wrap(Axis.prototype, 'renderUnsquish', function(proceed) {
363 if (this.options.grid) { 363 if (this.options.grid) {
364 this.labelRotation = 0; 364 this.labelRotation = 0;
365 this.options.labels.rotation = 0; 365 this.options.labels.rotation = 0;
366 } 366 }
367 proceed.apply(this); 367 proceed.apply(this);
368 }); 368 });
369   369  
370 /** 370 /**
371 * Places leftmost tick at the start of the axis, to create a left wall. 371 * Places leftmost tick at the start of the axis, to create a left wall.
372 * 372 *
373 * @param {function} proceed - the original function 373 * @param {function} proceed - the original function
374 */ 374 */
375 wrap(Axis.prototype, 'setOptions', function(proceed, userOptions) { 375 wrap(Axis.prototype, 'setOptions', function(proceed, userOptions) {
376 var axis = this; 376 var axis = this;
377 if (userOptions.grid && axis.horiz) { 377 if (userOptions.grid && axis.horiz) {
378 userOptions.startOnTick = true; 378 userOptions.startOnTick = true;
379 userOptions.minPadding = 0; 379 userOptions.minPadding = 0;
380 userOptions.endOnTick = true; 380 userOptions.endOnTick = true;
381 } 381 }
382 proceed.apply(this, Array.prototype.slice.call(arguments, 1)); 382 proceed.apply(this, Array.prototype.slice.call(arguments, 1));
383 }); 383 });
384   384  
385 /** 385 /**
386 * Draw an extra line on the far side of the the axisLine, 386 * Draw an extra line on the far side of the the axisLine,
387 * creating cell roofs of a grid. 387 * creating cell roofs of a grid.
388 * 388 *
389 * @param {function} proceed - the original function 389 * @param {function} proceed - the original function
390 */ 390 */
391 wrap(Axis.prototype, 'render', function(proceed) { 391 wrap(Axis.prototype, 'render', function(proceed) {
392 var axis = this, 392 var axis = this,
393 options = axis.options, 393 options = axis.options,
394 labelPadding, 394 labelPadding,
395 distance, 395 distance,
396 lineWidth, 396 lineWidth,
397 linePath, 397 linePath,
398 yStartIndex, 398 yStartIndex,
399 yEndIndex, 399 yEndIndex,
400 xStartIndex, 400 xStartIndex,
401 xEndIndex, 401 xEndIndex,
402 renderer = axis.chart.renderer, 402 renderer = axis.chart.renderer,
403 axisGroupBox; 403 axisGroupBox;
404   404  
405 if (options.grid) { 405 if (options.grid) {
406 labelPadding = (Math.abs(axis.defaultLeftAxisOptions.labels.x) * 2); 406 labelPadding = (Math.abs(axis.defaultLeftAxisOptions.labels.x) * 2);
407 distance = axis.maxLabelLength + labelPadding; 407 distance = axis.maxLabelLength + labelPadding;
408 lineWidth = options.lineWidth; 408 lineWidth = options.lineWidth;
409   409  
410 // Remove right wall before rendering 410 // Remove right wall before rendering
411 if (axis.rightWall) { 411 if (axis.rightWall) {
412 axis.rightWall.destroy(); 412 axis.rightWall.destroy();
413 } 413 }
414   414  
415 // Call original Axis.render() to obtain axis.axisLine and 415 // Call original Axis.render() to obtain axis.axisLine and
416 // axis.axisGroup 416 // axis.axisGroup
417 proceed.apply(axis); 417 proceed.apply(axis);
418   418  
419 axisGroupBox = axis.axisGroup.getBBox(); 419 axisGroupBox = axis.axisGroup.getBBox();
420   420  
421 // Add right wall on horizontal axes 421 // Add right wall on horizontal axes
422 if (axis.horiz) { 422 if (axis.horiz) {
423 axis.rightWall = renderer.path([ 423 axis.rightWall = renderer.path([
424 'M', 424 'M',
425 axisGroupBox.x + axis.width + 1, // account for left wall 425 axisGroupBox.x + axis.width + 1, // account for left wall
426 axisGroupBox.y, 426 axisGroupBox.y,
427 'L', 427 'L',
428 axisGroupBox.x + axis.width + 1, // account for left wall 428 axisGroupBox.x + axis.width + 1, // account for left wall
429 axisGroupBox.y + axisGroupBox.height 429 axisGroupBox.y + axisGroupBox.height
430 ]) 430 ])
431 .attr({ 431 .attr({
432 stroke: options.tickColor || '#ccd6eb', 432 stroke: options.tickColor || '#ccd6eb',
433 'stroke-width': options.tickWidth || 1, 433 'stroke-width': options.tickWidth || 1,
434 zIndex: 7, 434 zIndex: 7,
435 class: 'grid-wall' 435 class: 'grid-wall'
436 }) 436 })
437 .add(axis.axisGroup); 437 .add(axis.axisGroup);
438 } 438 }
439   439  
440 if (axis.isOuterAxis() && axis.axisLine) { 440 if (axis.isOuterAxis() && axis.axisLine) {
441 if (axis.horiz) { 441 if (axis.horiz) {
442 // -1 to avoid adding distance each time the chart updates 442 // -1 to avoid adding distance each time the chart updates
443 distance = axisGroupBox.height - 1; 443 distance = axisGroupBox.height - 1;
444 } 444 }
445   445  
446 if (lineWidth) { 446 if (lineWidth) {
447 linePath = axis.getLinePath(lineWidth); 447 linePath = axis.getLinePath(lineWidth);
448 xStartIndex = linePath.indexOf('M') + 1; 448 xStartIndex = linePath.indexOf('M') + 1;
449 xEndIndex = linePath.indexOf('L') + 1; 449 xEndIndex = linePath.indexOf('L') + 1;
450 yStartIndex = linePath.indexOf('M') + 2; 450 yStartIndex = linePath.indexOf('M') + 2;
451 yEndIndex = linePath.indexOf('L') + 2; 451 yEndIndex = linePath.indexOf('L') + 2;
452   452  
453 // Negate distance if top or left axis 453 // Negate distance if top or left axis
454 if (axis.side === axisSide.top || axis.side === axisSide.left) { 454 if (axis.side === axisSide.top || axis.side === axisSide.left) {
455 distance = -distance; 455 distance = -distance;
456 } 456 }
457   457  
458 // If axis is horizontal, reposition line path vertically 458 // If axis is horizontal, reposition line path vertically
459 if (axis.horiz) { 459 if (axis.horiz) {
460 linePath[yStartIndex] = linePath[yStartIndex] + distance; 460 linePath[yStartIndex] = linePath[yStartIndex] + distance;
461 linePath[yEndIndex] = linePath[yEndIndex] + distance; 461 linePath[yEndIndex] = linePath[yEndIndex] + distance;
462 } else { 462 } else {
463 // If axis is vertical, reposition line path horizontally 463 // If axis is vertical, reposition line path horizontally
464 linePath[xStartIndex] = linePath[xStartIndex] + distance; 464 linePath[xStartIndex] = linePath[xStartIndex] + distance;
465 linePath[xEndIndex] = linePath[xEndIndex] + distance; 465 linePath[xEndIndex] = linePath[xEndIndex] + distance;
466 } 466 }
467   467  
468 if (!axis.axisLineExtra) { 468 if (!axis.axisLineExtra) {
469 axis.axisLineExtra = renderer.path(linePath) 469 axis.axisLineExtra = renderer.path(linePath)
470 .attr({ 470 .attr({
471 stroke: options.lineColor, 471 stroke: options.lineColor,
472 'stroke-width': lineWidth, 472 'stroke-width': lineWidth,
473 zIndex: 7 473 zIndex: 7
474 }) 474 })
475 .add(axis.axisGroup); 475 .add(axis.axisGroup);
476 } else { 476 } else {
477 axis.axisLineExtra.animate({ 477 axis.axisLineExtra.animate({
478 d: linePath 478 d: linePath
479 }); 479 });
480 } 480 }
481   481  
482 // show or hide the line depending on options.showEmpty 482 // show or hide the line depending on options.showEmpty
483 axis.axisLine[axis.showAxis ? 'show' : 'hide'](true); 483 axis.axisLine[axis.showAxis ? 'show' : 'hide'](true);
484 } 484 }
485 } 485 }
486 } else { 486 } else {
487 proceed.apply(axis); 487 proceed.apply(axis);
488 } 488 }
489 }); 489 });
490   490  
491 /** 491 /**
492 * Wraps chart rendering with the following customizations: 492 * Wraps chart rendering with the following customizations:
493 * 1. Prohibit timespans of multitudes of a time unit 493 * 1. Prohibit timespans of multitudes of a time unit
494 * 2. Draw cell walls on vertical axes 494 * 2. Draw cell walls on vertical axes
495 * 495 *
496 * @param {function} proceed - the original function 496 * @param {function} proceed - the original function
497 */ 497 */
498 wrap(Chart.prototype, 'render', function(proceed) { 498 wrap(Chart.prototype, 'render', function(proceed) {
499 // 25 is optimal height for default fontSize (11px) 499 // 25 is optimal height for default fontSize (11px)
500 // 25 / 11 ≈ 2.28 500 // 25 / 11 ≈ 2.28
501 var fontSizeToCellHeightRatio = 25 / 11, 501 var fontSizeToCellHeightRatio = 25 / 11,
502 fontMetrics, 502 fontMetrics,
503 fontSize; 503 fontSize;
504   504  
505 each(this.axes, function(axis) { 505 each(this.axes, function(axis) {
506 var options = axis.options; 506 var options = axis.options;
507 if (options.grid) { 507 if (options.grid) {
508 fontSize = options.labels.style.fontSize; 508 fontSize = options.labels.style.fontSize;
509 fontMetrics = axis.chart.renderer.fontMetrics(fontSize); 509 fontMetrics = axis.chart.renderer.fontMetrics(fontSize);
510   510  
511 // Prohibit timespans of multitudes of a time unit, 511 // Prohibit timespans of multitudes of a time unit,
512 // e.g. two days, three weeks, etc. 512 // e.g. two days, three weeks, etc.
513 if (options.type === 'datetime') { 513 if (options.type === 'datetime') {
514 options.units = [ 514 options.units = [
515 ['millisecond', [1]], 515 ['millisecond', [1]],
516 ['second', [1]], 516 ['second', [1]],
517 ['minute', [1]], 517 ['minute', [1]],
518 ['hour', [1]], 518 ['hour', [1]],
519 ['day', [1]], 519 ['day', [1]],
520 ['week', [1]], 520 ['week', [1]],
521 ['month', [1]], 521 ['month', [1]],
522 ['year', null] 522 ['year', null]
523 ]; 523 ];
524 } 524 }
525   525  
526 // Make tick marks taller, creating cell walls of a grid. 526 // Make tick marks taller, creating cell walls of a grid.
527 // Use cellHeight axis option if set 527 // Use cellHeight axis option if set
528 if (axis.horiz) { 528 if (axis.horiz) {
529 options.tickLength = options.cellHeight || 529 options.tickLength = options.cellHeight ||
530 fontMetrics.h * fontSizeToCellHeightRatio; 530 fontMetrics.h * fontSizeToCellHeightRatio;
531 } else { 531 } else {
532 options.tickWidth = 1; 532 options.tickWidth = 1;
533 if (!options.lineWidth) { 533 if (!options.lineWidth) {
534 options.lineWidth = 1; 534 options.lineWidth = 1;
535 } 535 }
536 } 536 }
537 } 537 }
538 }); 538 });
539   539  
540 // Call original Chart.render() 540 // Call original Chart.render()
541 proceed.apply(this); 541 proceed.apply(this);
542 }); 542 });
543   543  
544 }(Highcharts)); 544 }(Highcharts));
545 (function(H) { 545 (function(H) {
546 /** 546 /**
547 * (c) 2014-2017 Highsoft AS 547 * (c) 2014-2017 Highsoft AS
548 * Authors: Torstein Honsi, Lars A. V. Cabrera 548 * Authors: Torstein Honsi, Lars A. V. Cabrera
549 * 549 *
550 * License: www.highcharts.com/license 550 * License: www.highcharts.com/license
551 */ 551 */
552   552  
553 var defaultPlotOptions = H.getOptions().plotOptions, 553 var defaultPlotOptions = H.getOptions().plotOptions,
554 color = H.Color, 554 color = H.Color,
555 columnType = H.seriesTypes.column, 555 columnType = H.seriesTypes.column,
556 each = H.each, 556 each = H.each,
557 extendClass = H.extendClass, 557 extendClass = H.extendClass,
558 isNumber = H.isNumber, 558 isNumber = H.isNumber,
559 isObject = H.isObject, 559 isObject = H.isObject,
560 merge = H.merge, 560 merge = H.merge,
561 pick = H.pick, 561 pick = H.pick,
562 seriesTypes = H.seriesTypes, 562 seriesTypes = H.seriesTypes,
563 wrap = H.wrap, 563 wrap = H.wrap,
564 Axis = H.Axis, 564 Axis = H.Axis,
565 Point = H.Point, 565 Point = H.Point,
566 Series = H.Series, 566 Series = H.Series,
567 pointFormat = '<span style="color:{point.color}">' + 567 pointFormat = '<span style="color:{point.color}">' +
568 '\u25CF' + 568 '\u25CF' +
569 '</span> {series.name}: <b>{point.yCategory}</b><br/>', 569 '</span> {series.name}: <b>{point.yCategory}</b><br/>',
570 xrange = 'xrange'; 570 xrange = 'xrange';
571   571  
572 defaultPlotOptions.xrange = merge(defaultPlotOptions.column, { 572 defaultPlotOptions.xrange = merge(defaultPlotOptions.column, {
573 tooltip: { 573 tooltip: {
574 pointFormat: pointFormat 574 pointFormat: pointFormat
575 } 575 }
576 }); 576 });
577 seriesTypes.xrange = extendClass(columnType, { 577 seriesTypes.xrange = extendClass(columnType, {
578 pointClass: extendClass(Point, { 578 pointClass: extendClass(Point, {
579 // Add x2 and yCategory to the available properties for tooltip formats 579 // Add x2 and yCategory to the available properties for tooltip formats
580 getLabelConfig: function() { 580 getLabelConfig: function() {
581 var cfg = Point.prototype.getLabelConfig.call(this); 581 var cfg = Point.prototype.getLabelConfig.call(this);
582   582  
583 cfg.x2 = this.x2; 583 cfg.x2 = this.x2;
584 cfg.yCategory = this.yCategory = this.series.yAxis.categories && this.series.yAxis.categories[this.y]; 584 cfg.yCategory = this.yCategory = this.series.yAxis.categories && this.series.yAxis.categories[this.y];
585 return cfg; 585 return cfg;
586 } 586 }
587 }), 587 }),
588 type: xrange, 588 type: xrange,
589 forceDL: true, 589 forceDL: true,
590 parallelArrays: ['x', 'x2', 'y'], 590 parallelArrays: ['x', 'x2', 'y'],
591 requireSorting: false, 591 requireSorting: false,
592 animate: seriesTypes.line.prototype.animate, 592 animate: seriesTypes.line.prototype.animate,
593   593  
594 /** 594 /**
595 * Borrow the column series metrics, but with swapped axes. This gives free access 595 * Borrow the column series metrics, but with swapped axes. This gives free access
596 * to features like groupPadding, grouping, pointWidth etc. 596 * to features like groupPadding, grouping, pointWidth etc.
597 */ 597 */
598 getColumnMetrics: function() { 598 getColumnMetrics: function() {
599 var metrics, 599 var metrics,
600 chart = this.chart; 600 chart = this.chart;
601   601  
602 function swapAxes() { 602 function swapAxes() {
603 each(chart.series, function(s) { 603 each(chart.series, function(s) {
604 var xAxis = s.xAxis; 604 var xAxis = s.xAxis;
605 s.xAxis = s.yAxis; 605 s.xAxis = s.yAxis;
606 s.yAxis = xAxis; 606 s.yAxis = xAxis;
607 }); 607 });
608 } 608 }
609   609  
610 swapAxes(); 610 swapAxes();
611   611  
612 this.yAxis.closestPointRange = 1; 612 this.yAxis.closestPointRange = 1;
613 metrics = columnType.prototype.getColumnMetrics.call(this); 613 metrics = columnType.prototype.getColumnMetrics.call(this);
614   614  
615 swapAxes(); 615 swapAxes();
616   616  
617 return metrics; 617 return metrics;
618 }, 618 },
619   619  
620 /** 620 /**
621 * Override cropData to show a point where x is outside visible range 621 * Override cropData to show a point where x is outside visible range
622 * but x2 is outside. 622 * but x2 is outside.
623 */ 623 */
624 cropData: function(xData, yData, min, max) { 624 cropData: function(xData, yData, min, max) {
625   625  
626 // Replace xData with x2Data to find the appropriate cropStart 626 // Replace xData with x2Data to find the appropriate cropStart
627 var cropData = Series.prototype.cropData, 627 var cropData = Series.prototype.cropData,
628 crop = cropData.call(this, this.x2Data, yData, min, max); 628 crop = cropData.call(this, this.x2Data, yData, min, max);
629   629  
630 // Re-insert the cropped xData 630 // Re-insert the cropped xData
631 crop.xData = xData.slice(crop.start, crop.end); 631 crop.xData = xData.slice(crop.start, crop.end);
632   632  
633 return crop; 633 return crop;
634 }, 634 },
635   635  
636 translate: function() { 636 translate: function() {
637 columnType.prototype.translate.apply(this, arguments); 637 columnType.prototype.translate.apply(this, arguments);
638 var series = this, 638 var series = this,
639 xAxis = series.xAxis, 639 xAxis = series.xAxis,
640 metrics = series.columnMetrics, 640 metrics = series.columnMetrics,
641 minPointLength = series.options.minPointLength || 0; 641 minPointLength = series.options.minPointLength || 0;
642   642  
643 each(series.points, function(point) { 643 each(series.points, function(point) {
644 var plotX = point.plotX, 644 var plotX = point.plotX,
645 posX = pick(point.x2, point.x + (point.len || 0)), 645 posX = pick(point.x2, point.x + (point.len || 0)),
646 plotX2 = xAxis.toPixels(posX, true), 646 plotX2 = xAxis.toPixels(posX, true),
647 width = plotX2 - plotX, 647 width = plotX2 - plotX,
648 widthDifference, 648 widthDifference,
649 shapeArgs, 649 shapeArgs,
650 partialFill; 650 partialFill;
651   651  
652 if (minPointLength) { 652 if (minPointLength) {
653 widthDifference = minPointLength - width; 653 widthDifference = minPointLength - width;
654 if (widthDifference < 0) { 654 if (widthDifference < 0) {
655 widthDifference = 0; 655 widthDifference = 0;
656 } 656 }
657 plotX -= widthDifference / 2; 657 plotX -= widthDifference / 2;
658 plotX2 += widthDifference / 2; 658 plotX2 += widthDifference / 2;
659 } 659 }
660   660  
661 plotX = Math.max(plotX, -10); 661 plotX = Math.max(plotX, -10);
662 plotX2 = Math.min(Math.max(plotX2, -10), xAxis.len + 10); 662 plotX2 = Math.min(Math.max(plotX2, -10), xAxis.len + 10);
663   663  
664 if (plotX2 < plotX) { // #6107 664 if (plotX2 < plotX) { // #6107
665 plotX2 = plotX; 665 plotX2 = plotX;
666 } 666 }
667   667  
668 point.shapeArgs = { 668 point.shapeArgs = {
669 x: plotX, 669 x: plotX,
670 y: point.plotY + metrics.offset, 670 y: point.plotY + metrics.offset,
671 width: plotX2 - plotX, 671 width: plotX2 - plotX,
672 height: metrics.width 672 height: metrics.width
673 }; 673 };
674 point.tooltipPos[0] += width / 2; 674 point.tooltipPos[0] += width / 2;
675 point.tooltipPos[1] -= metrics.width / 2; 675 point.tooltipPos[1] -= metrics.width / 2;
676   676  
677 // Add a partShapeArgs to the point, based on the shapeArgs property 677 // Add a partShapeArgs to the point, based on the shapeArgs property
678 partialFill = point.partialFill; 678 partialFill = point.partialFill;
679 if (partialFill) { 679 if (partialFill) {
680 // Get the partial fill amount 680 // Get the partial fill amount
681 if (isObject(partialFill)) { 681 if (isObject(partialFill)) {
682 partialFill = partialFill.amount; 682 partialFill = partialFill.amount;
683 } 683 }
684 // If it was not a number, assume 0 684 // If it was not a number, assume 0
685 if (!isNumber(partialFill)) { 685 if (!isNumber(partialFill)) {
686 partialFill = 0; 686 partialFill = 0;
687 } 687 }
688 shapeArgs = point.shapeArgs; 688 shapeArgs = point.shapeArgs;
689 point.partShapeArgs = { 689 point.partShapeArgs = {
690 x: shapeArgs.x, 690 x: shapeArgs.x,
691 y: shapeArgs.y + 1, 691 y: shapeArgs.y + 1,
692 width: shapeArgs.width * partialFill, 692 width: shapeArgs.width * partialFill,
693 height: shapeArgs.height - 2 693 height: shapeArgs.height - 2
694 }; 694 };
695 } 695 }
696 }); 696 });
697 }, 697 },
698   698  
699 drawPoints: function() { 699 drawPoints: function() {
700 var series = this, 700 var series = this,
701 chart = this.chart, 701 chart = this.chart,
702 options = series.options, 702 options = series.options,
703 renderer = chart.renderer, 703 renderer = chart.renderer,
704 animationLimit = options.animationLimit || 250, 704 animationLimit = options.animationLimit || 250,
705 verb = chart.pointCount < animationLimit ? 'animate' : 'attr'; 705 verb = chart.pointCount < animationLimit ? 'animate' : 'attr';
706   706  
707 // draw the columns 707 // draw the columns
708 each(series.points, function(point) { 708 each(series.points, function(point) {
709 var plotY = point.plotY, 709 var plotY = point.plotY,
710 graphic = point.graphic, 710 graphic = point.graphic,
711 type = point.shapeType, 711 type = point.shapeType,
712 shapeArgs = point.shapeArgs, 712 shapeArgs = point.shapeArgs,
713 partShapeArgs = point.partShapeArgs, 713 partShapeArgs = point.partShapeArgs,
714 seriesOpts = series.options, 714 seriesOpts = series.options,
715 pfOptions = point.partialFill, 715 pfOptions = point.partialFill,
716 fill, 716 fill,
717 state = point.selected && 'select', 717 state = point.selected && 'select',
718 cutOff = options.stacking && !options.borderRadius; 718 cutOff = options.stacking && !options.borderRadius;
719   719  
720 if (isNumber(plotY) && point.y !== null) { 720 if (isNumber(plotY) && point.y !== null) {
721 if (graphic) { // update 721 if (graphic) { // update
722 point.graphicOriginal[verb]( 722 point.graphicOriginal[verb](
723 merge(shapeArgs) 723 merge(shapeArgs)
724 ); 724 );
725 if (partShapeArgs) { 725 if (partShapeArgs) {
726 point.graphicOverlay[verb]( 726 point.graphicOverlay[verb](
727 merge(partShapeArgs) 727 merge(partShapeArgs)
728 ); 728 );
729 } 729 }
730   730  
731 } else { 731 } else {
732 point.graphic = graphic = renderer.g('point') 732 point.graphic = graphic = renderer.g('point')
733 .attr({ 733 .attr({
734 'class': point.getClassName() 734 'class': point.getClassName()
735 }) 735 })
736 .add(point.group || series.group); 736 .add(point.group || series.group);
737   737  
738 point.graphicOriginal = renderer[type](shapeArgs) 738 point.graphicOriginal = renderer[type](shapeArgs)
739 .addClass('highcharts-partfill-original') 739 .addClass('highcharts-partfill-original')
740 .add(graphic); 740 .add(graphic);
741 if (partShapeArgs) { 741 if (partShapeArgs) {
742 point.graphicOverlay = renderer[type](partShapeArgs) 742 point.graphicOverlay = renderer[type](partShapeArgs)
743 .addClass('highcharts-partfill-overlay') 743 .addClass('highcharts-partfill-overlay')
744 .add(graphic); 744 .add(graphic);
745 } 745 }
746 } 746 }
747   747  
748   748  
749   749  
750 } else if (graphic) { 750 } else if (graphic) {
751 point.graphic = graphic.destroy(); // #1269 751 point.graphic = graphic.destroy(); // #1269
752 } 752 }
753 }); 753 });
754 } 754 }
755 }); 755 });
756   756  
757 /** 757 /**
758 * Max x2 should be considered in xAxis extremes 758 * Max x2 should be considered in xAxis extremes
759 */ 759 */
760 wrap(Axis.prototype, 'getSeriesExtremes', function(proceed) { 760 wrap(Axis.prototype, 'getSeriesExtremes', function(proceed) {
761 var axis = this, 761 var axis = this,
762 series = axis.series, 762 series = axis.series,
763 dataMax, 763 dataMax,
764 modMax; 764 modMax;
765   765  
766 proceed.call(this); 766 proceed.call(this);
767 if (axis.isXAxis && series.type === xrange) { 767 if (axis.isXAxis && series.type === xrange) {
768 dataMax = pick(axis.dataMax, Number.MIN_VALUE); 768 dataMax = pick(axis.dataMax, Number.MIN_VALUE);
769 each(this.series, function(series) { 769 each(this.series, function(series) {
770 each(series.x2Data || [], function(val) { 770 each(series.x2Data || [], function(val) {
771 if (val > dataMax) { 771 if (val > dataMax) {
772 dataMax = val; 772 dataMax = val;
773 modMax = true; 773 modMax = true;
774 } 774 }
775 }); 775 });
776 }); 776 });
777 if (modMax) { 777 if (modMax) {
778 axis.dataMax = dataMax; 778 axis.dataMax = dataMax;
779 } 779 }
780 } 780 }
781 }); 781 });
782   782  
783 }(Highcharts)); 783 }(Highcharts));
784 (function(H) { 784 (function(H) {
785 /** 785 /**
786 * (c) 2016 Highsoft AS 786 * (c) 2016 Highsoft AS
787 * Authors: Lars A. V. Cabrera 787 * Authors: Lars A. V. Cabrera
788 * 788 *
789 * License: www.highcharts.com/license 789 * License: www.highcharts.com/license
790 */ 790 */
791 // 791 //
792 }(Highcharts)); 792 }(Highcharts));
793 })); 793 }));
794   794