/**
|
|
* Highcharts JS v4.1.8 (2015-08-20)
|
|
* Highcharts Broken Axis module
|
|
*
|
|
* Author: Stephane Vanraes, Torstein Honsi
|
|
* License: www.highcharts.com/license
|
|
*/
|
|
|
|
/*global HighchartsAdapter*/
|
|
(function (H) {
|
|
|
|
"use strict";
|
|
|
|
var pick = H.pick,
|
|
wrap = H.wrap,
|
|
extend = H.extend,
|
|
fireEvent = HighchartsAdapter.fireEvent,
|
|
Axis = H.Axis,
|
|
Series = H.Series;
|
|
|
|
function stripArguments() {
|
|
return Array.prototype.slice.call(arguments, 1);
|
|
}
|
|
|
|
extend(Axis.prototype, {
|
|
isInBreak: function (brk, val) {
|
|
var ret,
|
|
repeat = brk.repeat || Infinity,
|
|
from = brk.from,
|
|
length = brk.to - brk.from,
|
|
test = (val >= from ? (val - from) % repeat : repeat - ((from - val) % repeat));
|
|
|
|
if (!brk.inclusive) {
|
|
ret = test < length && test !== 0;
|
|
} else {
|
|
ret = test <= length;
|
|
}
|
|
return ret;
|
|
},
|
|
|
|
isInAnyBreak: function (val, testKeep) {
|
|
|
|
var breaks = this.options.breaks,
|
|
i = breaks && breaks.length,
|
|
inbrk,
|
|
keep,
|
|
ret;
|
|
|
|
|
|
if (i) {
|
|
|
|
while (i--) {
|
|
if (this.isInBreak(breaks[i], val)) {
|
|
inbrk = true;
|
|
if (!keep) {
|
|
keep = pick(breaks[i].showPoints, this.isXAxis ? false : true);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (inbrk && testKeep) {
|
|
ret = inbrk && !keep;
|
|
} else {
|
|
ret = inbrk;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
});
|
|
|
|
wrap(Axis.prototype, 'setTickPositions', function (proceed) {
|
|
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
|
|
|
|
if (this.options.breaks) {
|
|
var axis = this,
|
|
tickPositions = this.tickPositions,
|
|
info = this.tickPositions.info,
|
|
newPositions = [],
|
|
i;
|
|
|
|
if (info && info.totalRange >= axis.closestPointRange) {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < tickPositions.length; i++) {
|
|
if (!axis.isInAnyBreak(tickPositions[i])) {
|
|
newPositions.push(tickPositions[i]);
|
|
}
|
|
}
|
|
|
|
this.tickPositions = newPositions;
|
|
this.tickPositions.info = info;
|
|
}
|
|
});
|
|
|
|
wrap(Axis.prototype, 'init', function (proceed, chart, userOptions) {
|
|
// Force Axis to be not-ordinal when breaks are defined
|
|
if (userOptions.breaks && userOptions.breaks.length) {
|
|
userOptions.ordinal = false;
|
|
}
|
|
|
|
proceed.call(this, chart, userOptions);
|
|
|
|
if (this.options.breaks) {
|
|
|
|
var axis = this;
|
|
|
|
axis.doPostTranslate = true;
|
|
|
|
this.val2lin = function (val) {
|
|
var nval = val,
|
|
brk,
|
|
i;
|
|
|
|
for (i = 0; i < axis.breakArray.length; i++) {
|
|
brk = axis.breakArray[i];
|
|
if (brk.to <= val) {
|
|
nval -= brk.len;
|
|
} else if (brk.from >= val) {
|
|
break;
|
|
} else if (axis.isInBreak(brk, val)) {
|
|
nval -= (val - brk.from);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return nval;
|
|
};
|
|
|
|
this.lin2val = function (val) {
|
|
var nval = val,
|
|
brk,
|
|
i;
|
|
|
|
for (i = 0; i < axis.breakArray.length; i++) {
|
|
brk = axis.breakArray[i];
|
|
if (brk.from >= nval) {
|
|
break;
|
|
} else if (brk.to < nval) {
|
|
nval += brk.len;
|
|
} else if (axis.isInBreak(brk, nval)) {
|
|
nval += brk.len;
|
|
}
|
|
}
|
|
return nval;
|
|
};
|
|
|
|
this.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) {
|
|
// If trying to set extremes inside a break, extend it to before and after the break ( #3857 )
|
|
while (this.isInAnyBreak(newMin)) {
|
|
newMin -= this.closestPointRange;
|
|
}
|
|
while (this.isInAnyBreak(newMax)) {
|
|
newMax -= this.closestPointRange;
|
|
}
|
|
Axis.prototype.setExtremes.call(this, newMin, newMax, redraw, animation, eventArguments);
|
|
};
|
|
|
|
this.setAxisTranslation = function (saveOld) {
|
|
Axis.prototype.setAxisTranslation.call(this, saveOld);
|
|
|
|
var breaks = axis.options.breaks,
|
|
breakArrayT = [], // Temporary one
|
|
breakArray = [],
|
|
length = 0,
|
|
inBrk,
|
|
repeat,
|
|
brk,
|
|
min = axis.userMin || axis.min,
|
|
max = axis.userMax || axis.max,
|
|
start,
|
|
i,
|
|
j;
|
|
|
|
// Min & max check (#4247)
|
|
for (i in breaks) {
|
|
brk = breaks[i];
|
|
repeat = brk.repeat || Infinity;
|
|
if (axis.isInBreak(brk, min)) {
|
|
min += (brk.to % repeat) - (min % repeat);
|
|
}
|
|
if (axis.isInBreak(brk, max)) {
|
|
max -= (max % repeat) - (brk.from % repeat);
|
|
}
|
|
}
|
|
|
|
// Construct an array holding all breaks in the axis
|
|
for (i in breaks) {
|
|
brk = breaks[i];
|
|
start = brk.from;
|
|
repeat = brk.repeat || Infinity;
|
|
|
|
while (start - repeat > min) {
|
|
start -= repeat;
|
|
}
|
|
while (start < min) {
|
|
start += repeat;
|
|
}
|
|
|
|
for (j = start; j < max; j += repeat) {
|
|
breakArrayT.push({
|
|
value: j,
|
|
move: 'in'
|
|
});
|
|
breakArrayT.push({
|
|
value: j + (brk.to - brk.from),
|
|
move: 'out',
|
|
size: brk.breakSize
|
|
});
|
|
}
|
|
}
|
|
|
|
breakArrayT.sort(function (a, b) {
|
|
if (a.value === b.value) {
|
|
return (a.move === 'in' ? 0 : 1) - (b.move === 'in' ? 0 : 1);
|
|
} else {
|
|
return a.value - b.value;
|
|
}
|
|
});
|
|
|
|
// Simplify the breaks
|
|
inBrk = 0;
|
|
start = min;
|
|
|
|
for (i in breakArrayT) {
|
|
brk = breakArrayT[i];
|
|
inBrk += (brk.move === 'in' ? 1 : -1);
|
|
|
|
if (inBrk === 1 && brk.move === 'in') {
|
|
start = brk.value;
|
|
}
|
|
if (inBrk === 0) {
|
|
breakArray.push({
|
|
from: start,
|
|
to: brk.value,
|
|
len: brk.value - start - (brk.size || 0)
|
|
});
|
|
length += brk.value - start - (brk.size || 0);
|
|
}
|
|
}
|
|
|
|
axis.breakArray = breakArray;
|
|
|
|
fireEvent(axis, 'afterBreaks');
|
|
|
|
axis.transA *= ((max - axis.min) / (max - min - length));
|
|
|
|
axis.min = min;
|
|
axis.max = max;
|
|
};
|
|
}
|
|
});
|
|
|
|
wrap(Series.prototype, 'generatePoints', function (proceed) {
|
|
|
|
proceed.apply(this, stripArguments(arguments));
|
|
|
|
var series = this,
|
|
xAxis = series.xAxis,
|
|
yAxis = series.yAxis,
|
|
points = series.points,
|
|
point,
|
|
i = points.length,
|
|
connectNulls = series.options.connectNulls,
|
|
nullGap;
|
|
|
|
|
|
if (xAxis && yAxis && (xAxis.options.breaks || yAxis.options.breaks)) {
|
|
while (i--) {
|
|
point = points[i];
|
|
|
|
nullGap = point.y === null && connectNulls === false; // respect nulls inside the break (#4275)
|
|
if (!nullGap && (xAxis.isInAnyBreak(point.x, true) || yAxis.isInAnyBreak(point.y, true))) {
|
|
points.splice(i, 1);
|
|
if (this.data[i]) {
|
|
this.data[i].destroyElements(); // removes the graphics for this point if they exist
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
wrap(H.seriesTypes.column.prototype, 'drawPoints', function (proceed) {
|
|
proceed.apply(this);
|
|
|
|
var series = this,
|
|
points = series.points,
|
|
yAxis = series.yAxis,
|
|
breaks = yAxis.breakArray || [],
|
|
threshold = pick(this.options.threshold, yAxis.min),
|
|
eventName,
|
|
point,
|
|
brk,
|
|
i,
|
|
j,
|
|
y;
|
|
|
|
for (i = 0; i < points.length; i++) {
|
|
point = points[i];
|
|
y = point.stackY || point.y;
|
|
for (j = 0; j < breaks.length; j++) {
|
|
brk = breaks[j];
|
|
eventName = false;
|
|
|
|
if ((threshold < brk.from && y > brk.to) || (threshold > brk.from && y < brk.from)) {
|
|
eventName = 'pointBreak';
|
|
} 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
|
|
eventName = 'pointInBreak'; // docs
|
|
}
|
|
if (eventName) {
|
|
fireEvent(yAxis, eventName, {point: point, brk: brk});
|
|
}
|
|
}
|
|
}
|
|
|
|
});
|
|
}(Highcharts));
|