You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

318 lines
7.1 KiB

9 years ago
  1. /**
  2. * Highcharts JS v4.1.8 (2015-08-20)
  3. * Highcharts Broken Axis module
  4. *
  5. * Author: Stephane Vanraes, Torstein Honsi
  6. * License: www.highcharts.com/license
  7. */
  8. /*global HighchartsAdapter*/
  9. (function (H) {
  10. "use strict";
  11. var pick = H.pick,
  12. wrap = H.wrap,
  13. extend = H.extend,
  14. fireEvent = HighchartsAdapter.fireEvent,
  15. Axis = H.Axis,
  16. Series = H.Series;
  17. function stripArguments() {
  18. return Array.prototype.slice.call(arguments, 1);
  19. }
  20. extend(Axis.prototype, {
  21. isInBreak: function (brk, val) {
  22. var ret,
  23. repeat = brk.repeat || Infinity,
  24. from = brk.from,
  25. length = brk.to - brk.from,
  26. test = (val >= from ? (val - from) % repeat : repeat - ((from - val) % repeat));
  27. if (!brk.inclusive) {
  28. ret = test < length && test !== 0;
  29. } else {
  30. ret = test <= length;
  31. }
  32. return ret;
  33. },
  34. isInAnyBreak: function (val, testKeep) {
  35. var breaks = this.options.breaks,
  36. i = breaks && breaks.length,
  37. inbrk,
  38. keep,
  39. ret;
  40. if (i) {
  41. while (i--) {
  42. if (this.isInBreak(breaks[i], val)) {
  43. inbrk = true;
  44. if (!keep) {
  45. keep = pick(breaks[i].showPoints, this.isXAxis ? false : true);
  46. }
  47. }
  48. }
  49. if (inbrk && testKeep) {
  50. ret = inbrk && !keep;
  51. } else {
  52. ret = inbrk;
  53. }
  54. }
  55. return ret;
  56. }
  57. });
  58. wrap(Axis.prototype, 'setTickPositions', function (proceed) {
  59. proceed.apply(this, Array.prototype.slice.call(arguments, 1));
  60. if (this.options.breaks) {
  61. var axis = this,
  62. tickPositions = this.tickPositions,
  63. info = this.tickPositions.info,
  64. newPositions = [],
  65. i;
  66. if (info && info.totalRange >= axis.closestPointRange) {
  67. return;
  68. }
  69. for (i = 0; i < tickPositions.length; i++) {
  70. if (!axis.isInAnyBreak(tickPositions[i])) {
  71. newPositions.push(tickPositions[i]);
  72. }
  73. }
  74. this.tickPositions = newPositions;
  75. this.tickPositions.info = info;
  76. }
  77. });
  78. wrap(Axis.prototype, 'init', function (proceed, chart, userOptions) {
  79. // Force Axis to be not-ordinal when breaks are defined
  80. if (userOptions.breaks && userOptions.breaks.length) {
  81. userOptions.ordinal = false;
  82. }
  83. proceed.call(this, chart, userOptions);
  84. if (this.options.breaks) {
  85. var axis = this;
  86. axis.doPostTranslate = true;
  87. this.val2lin = function (val) {
  88. var nval = val,
  89. brk,
  90. i;
  91. for (i = 0; i < axis.breakArray.length; i++) {
  92. brk = axis.breakArray[i];
  93. if (brk.to <= val) {
  94. nval -= brk.len;
  95. } else if (brk.from >= val) {
  96. break;
  97. } else if (axis.isInBreak(brk, val)) {
  98. nval -= (val - brk.from);
  99. break;
  100. }
  101. }
  102. return nval;
  103. };
  104. this.lin2val = function (val) {
  105. var nval = val,
  106. brk,
  107. i;
  108. for (i = 0; i < axis.breakArray.length; i++) {
  109. brk = axis.breakArray[i];
  110. if (brk.from >= nval) {
  111. break;
  112. } else if (brk.to < nval) {
  113. nval += brk.len;
  114. } else if (axis.isInBreak(brk, nval)) {
  115. nval += brk.len;
  116. }
  117. }
  118. return nval;
  119. };
  120. this.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) {
  121. // If trying to set extremes inside a break, extend it to before and after the break ( #3857 )
  122. while (this.isInAnyBreak(newMin)) {
  123. newMin -= this.closestPointRange;
  124. }
  125. while (this.isInAnyBreak(newMax)) {
  126. newMax -= this.closestPointRange;
  127. }
  128. Axis.prototype.setExtremes.call(this, newMin, newMax, redraw, animation, eventArguments);
  129. };
  130. this.setAxisTranslation = function (saveOld) {
  131. Axis.prototype.setAxisTranslation.call(this, saveOld);
  132. var breaks = axis.options.breaks,
  133. breakArrayT = [], // Temporary one
  134. breakArray = [],
  135. length = 0,
  136. inBrk,
  137. repeat,
  138. brk,
  139. min = axis.userMin || axis.min,
  140. max = axis.userMax || axis.max,
  141. start,
  142. i,
  143. j;
  144. // Min & max check (#4247)
  145. for (i in breaks) {
  146. brk = breaks[i];
  147. repeat = brk.repeat || Infinity;
  148. if (axis.isInBreak(brk, min)) {
  149. min += (brk.to % repeat) - (min % repeat);
  150. }
  151. if (axis.isInBreak(brk, max)) {
  152. max -= (max % repeat) - (brk.from % repeat);
  153. }
  154. }
  155. // Construct an array holding all breaks in the axis
  156. for (i in breaks) {
  157. brk = breaks[i];
  158. start = brk.from;
  159. repeat = brk.repeat || Infinity;
  160. while (start - repeat > min) {
  161. start -= repeat;
  162. }
  163. while (start < min) {
  164. start += repeat;
  165. }
  166. for (j = start; j < max; j += repeat) {
  167. breakArrayT.push({
  168. value: j,
  169. move: 'in'
  170. });
  171. breakArrayT.push({
  172. value: j + (brk.to - brk.from),
  173. move: 'out',
  174. size: brk.breakSize
  175. });
  176. }
  177. }
  178. breakArrayT.sort(function (a, b) {
  179. if (a.value === b.value) {
  180. return (a.move === 'in' ? 0 : 1) - (b.move === 'in' ? 0 : 1);
  181. } else {
  182. return a.value - b.value;
  183. }
  184. });
  185. // Simplify the breaks
  186. inBrk = 0;
  187. start = min;
  188. for (i in breakArrayT) {
  189. brk = breakArrayT[i];
  190. inBrk += (brk.move === 'in' ? 1 : -1);
  191. if (inBrk === 1 && brk.move === 'in') {
  192. start = brk.value;
  193. }
  194. if (inBrk === 0) {
  195. breakArray.push({
  196. from: start,
  197. to: brk.value,
  198. len: brk.value - start - (brk.size || 0)
  199. });
  200. length += brk.value - start - (brk.size || 0);
  201. }
  202. }
  203. axis.breakArray = breakArray;
  204. fireEvent(axis, 'afterBreaks');
  205. axis.transA *= ((max - axis.min) / (max - min - length));
  206. axis.min = min;
  207. axis.max = max;
  208. };
  209. }
  210. });
  211. wrap(Series.prototype, 'generatePoints', function (proceed) {
  212. proceed.apply(this, stripArguments(arguments));
  213. var series = this,
  214. xAxis = series.xAxis,
  215. yAxis = series.yAxis,
  216. points = series.points,
  217. point,
  218. i = points.length,
  219. connectNulls = series.options.connectNulls,
  220. nullGap;
  221. if (xAxis && yAxis && (xAxis.options.breaks || yAxis.options.breaks)) {
  222. while (i--) {
  223. point = points[i];
  224. nullGap = point.y === null && connectNulls === false; // respect nulls inside the break (#4275)
  225. if (!nullGap && (xAxis.isInAnyBreak(point.x, true) || yAxis.isInAnyBreak(point.y, true))) {
  226. points.splice(i, 1);
  227. if (this.data[i]) {
  228. this.data[i].destroyElements(); // removes the graphics for this point if they exist
  229. }
  230. }
  231. }
  232. }
  233. });
  234. wrap(H.seriesTypes.column.prototype, 'drawPoints', function (proceed) {
  235. proceed.apply(this);
  236. var series = this,
  237. points = series.points,
  238. yAxis = series.yAxis,
  239. breaks = yAxis.breakArray || [],
  240. threshold = pick(this.options.threshold, yAxis.min),
  241. eventName,
  242. point,
  243. brk,
  244. i,
  245. j,
  246. y;
  247. for (i = 0; i < points.length; i++) {
  248. point = points[i];
  249. y = point.stackY || point.y;
  250. for (j = 0; j < breaks.length; j++) {
  251. brk = breaks[j];
  252. eventName = false;
  253. if ((threshold < brk.from && y > brk.to) || (threshold > brk.from && y < brk.from)) {
  254. eventName = 'pointBreak';
  255. } else if ((threshold < brk.from && y > brk.from && y < brk.to) || (threshold > brk.from && y > brk.to && y < brk.from)) { // point falls inside the break
  256. eventName = 'pointInBreak'; // docs
  257. }
  258. if (eventName) {
  259. fireEvent(yAxis, eventName, {point: point, brk: brk});
  260. }
  261. }
  262. }
  263. });
  264. }(Highcharts));