broken-axis.src.js 12 KB

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