broken-axis.src.js 6.6 KB

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