|
|
@ -28,17 +28,15 @@ function DataAxis (body, options, svg, linegraphOptions) { |
|
|
|
width: '40px', |
|
|
|
visible: true, |
|
|
|
alignZeros: true, |
|
|
|
customRange: { |
|
|
|
left: {min:undefined, max:undefined}, |
|
|
|
right: {min:undefined, max:undefined} |
|
|
|
left:{ |
|
|
|
range: {min:undefined,max:undefined}, |
|
|
|
format: {decimals:undefined}, |
|
|
|
title: {text:undefined,style:undefined} |
|
|
|
}, |
|
|
|
title: { |
|
|
|
left: {text:undefined}, |
|
|
|
right: {text:undefined} |
|
|
|
}, |
|
|
|
format: { |
|
|
|
left: {decimals: undefined}, |
|
|
|
right: {decimals: undefined} |
|
|
|
right:{ |
|
|
|
range: {min:undefined,max:undefined}, |
|
|
|
format: {decimals:undefined}, |
|
|
|
title: {text:undefined,style:undefined} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
@ -65,8 +63,8 @@ function DataAxis (body, options, svg, linegraphOptions) { |
|
|
|
this.hidden = false; |
|
|
|
|
|
|
|
this.stepPixels = 25; |
|
|
|
this.stepPixelsForced = 25; |
|
|
|
this.zeroCrossing = -1; |
|
|
|
this.amountOfSteps = -1; |
|
|
|
|
|
|
|
this.lineOffset = 0; |
|
|
|
this.master = true; |
|
|
@ -126,16 +124,15 @@ DataAxis.prototype.setOptions = function (options) { |
|
|
|
'iconWidth', |
|
|
|
'width', |
|
|
|
'visible', |
|
|
|
'customRange', |
|
|
|
'title', |
|
|
|
'format', |
|
|
|
'left', |
|
|
|
'right', |
|
|
|
'alignZeros' |
|
|
|
]; |
|
|
|
util.selectiveExtend(fields, this.options, options); |
|
|
|
|
|
|
|
this.minWidth = Number(('' + this.options.width).replace("px","")); |
|
|
|
|
|
|
|
if (redraw == true && this.dom.frame) { |
|
|
|
if (redraw === true && this.dom.frame) { |
|
|
|
this.hide(); |
|
|
|
this.show(); |
|
|
|
} |
|
|
@ -175,19 +172,23 @@ DataAxis.prototype._redrawGroupIcons = function () { |
|
|
|
var iconOffset = 4; |
|
|
|
var y = iconOffset + 0.5 * iconHeight; |
|
|
|
|
|
|
|
if (this.options.orientation == 'left') { |
|
|
|
if (this.options.orientation === 'left') { |
|
|
|
x = iconOffset; |
|
|
|
} |
|
|
|
else { |
|
|
|
x = this.width - iconWidth - iconOffset; |
|
|
|
} |
|
|
|
|
|
|
|
for (var groupId in this.groups) { |
|
|
|
if (this.groups.hasOwnProperty(groupId)) { |
|
|
|
if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) { |
|
|
|
this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight); |
|
|
|
y += iconHeight + iconOffset; |
|
|
|
} |
|
|
|
var groupArray = Object.keys(this.groups); |
|
|
|
groupArray.sort(function (a,b) { |
|
|
|
return (a < b ? -1 : 1); |
|
|
|
}) |
|
|
|
|
|
|
|
for (var i = 0; i < groupArray.length; i++) { |
|
|
|
var groupId = groupArray[i]; |
|
|
|
if (this.groups[groupId].visible === true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] === true)) { |
|
|
|
this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight); |
|
|
|
y += iconHeight + iconOffset; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -196,7 +197,7 @@ DataAxis.prototype._redrawGroupIcons = function () { |
|
|
|
}; |
|
|
|
|
|
|
|
DataAxis.prototype._cleanupIcons = function() { |
|
|
|
if (this.iconsRemoved == false) { |
|
|
|
if (this.iconsRemoved === false) { |
|
|
|
DOMutil.prepareElements(this.svgElements); |
|
|
|
DOMutil.cleanupElements(this.svgElements); |
|
|
|
this.iconsRemoved = true; |
|
|
@ -209,7 +210,7 @@ DataAxis.prototype._cleanupIcons = function() { |
|
|
|
DataAxis.prototype.show = function() { |
|
|
|
this.hidden = false; |
|
|
|
if (!this.dom.frame.parentNode) { |
|
|
|
if (this.options.orientation == 'left') { |
|
|
|
if (this.options.orientation === 'left') { |
|
|
|
this.body.dom.left.appendChild(this.dom.frame); |
|
|
|
} |
|
|
|
else { |
|
|
@ -243,7 +244,7 @@ DataAxis.prototype.hide = function() { |
|
|
|
* @param end |
|
|
|
*/ |
|
|
|
DataAxis.prototype.setRange = function (start, end) { |
|
|
|
if (this.master == false && this.options.alignZeros == true && this.zeroCrossing != -1) { |
|
|
|
if (this.master === false && this.options.alignZeros === true && this.zeroCrossing != -1) { |
|
|
|
if (start > 0) { |
|
|
|
start = 0; |
|
|
|
} |
|
|
@ -265,12 +266,12 @@ DataAxis.prototype.redraw = function () { |
|
|
|
|
|
|
|
for (var groupId in this.groups) { |
|
|
|
if (this.groups.hasOwnProperty(groupId)) { |
|
|
|
if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) { |
|
|
|
if (this.groups[groupId].visible === true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] === true)) { |
|
|
|
activeGroups++; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (this.amountOfGroups == 0 || activeGroups == 0) { |
|
|
|
if (this.amountOfGroups === 0 || activeGroups === 0) { |
|
|
|
this.hide(); |
|
|
|
} |
|
|
|
else { |
|
|
@ -279,7 +280,7 @@ DataAxis.prototype.redraw = function () { |
|
|
|
|
|
|
|
// svg offsetheight did not work in firefox and explorer...
|
|
|
|
this.dom.lineContainer.style.height = this.height + 'px'; |
|
|
|
this.width = this.options.visible == true ? Number(('' + this.options.width).replace("px","")) : 0; |
|
|
|
this.width = this.options.visible === true ? Number(('' + this.options.width).replace("px","")) : 0; |
|
|
|
|
|
|
|
var props = this.props; |
|
|
|
var frame = this.dom.frame; |
|
|
@ -304,7 +305,7 @@ DataAxis.prototype.redraw = function () { |
|
|
|
props.majorLineHeight = 1; |
|
|
|
|
|
|
|
// take frame offline while updating (is almost twice as fast)
|
|
|
|
if (orientation == 'left') { |
|
|
|
if (orientation === 'left') { |
|
|
|
frame.style.top = '0'; |
|
|
|
frame.style.left = '0'; |
|
|
|
frame.style.bottom = ''; |
|
|
@ -326,7 +327,7 @@ DataAxis.prototype.redraw = function () { |
|
|
|
resized = this._redrawLabels(); |
|
|
|
resized = this._isResized() || resized; |
|
|
|
|
|
|
|
if (this.options.icons == true) { |
|
|
|
if (this.options.icons === true) { |
|
|
|
this._redrawGroupIcons(); |
|
|
|
} |
|
|
|
else { |
|
|
@ -346,113 +347,121 @@ DataAxis.prototype._redrawLabels = function () { |
|
|
|
var resized = false; |
|
|
|
DOMutil.prepareElements(this.DOMelements.lines); |
|
|
|
DOMutil.prepareElements(this.DOMelements.labels); |
|
|
|
|
|
|
|
var orientation = this.options['orientation']; |
|
|
|
|
|
|
|
// calculate range and step (step such that we have space for 7 characters per label)
|
|
|
|
var minimumStep = this.master ? this.props.majorCharHeight || 10 : this.stepPixelsForced; |
|
|
|
// get the range for the slaved axis
|
|
|
|
var step; |
|
|
|
if (this.master === false) { |
|
|
|
var stepSize, rangeStart, rangeEnd, minimumStep; |
|
|
|
if (this.zeroCrossing !== -1 && this.options.alignZeros === true) { |
|
|
|
if (this.range.end > 0) { |
|
|
|
stepSize = this.range.end / this.zeroCrossing; // size of one step
|
|
|
|
rangeStart = this.range.end - this.amountOfSteps * stepSize; |
|
|
|
rangeEnd = this.range.end; |
|
|
|
} |
|
|
|
else { |
|
|
|
// all of the range (including start) has to be done before the zero crossing.
|
|
|
|
stepSize = -1 * this.range.start / (this.amountOfSteps - this.zeroCrossing); // absolute size of a step
|
|
|
|
rangeStart = this.range.start; |
|
|
|
rangeEnd = this.range.start + stepSize * this.amountOfSteps; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
rangeStart = this.range.start; |
|
|
|
rangeEnd = this.range.end; |
|
|
|
} |
|
|
|
minimumStep = this.stepPixels; |
|
|
|
} |
|
|
|
else { |
|
|
|
// calculate range and step (step such that we have space for 7 characters per label)
|
|
|
|
minimumStep = this.props.majorCharHeight; |
|
|
|
rangeStart = this.range.start; |
|
|
|
rangeEnd = this.range.end; |
|
|
|
} |
|
|
|
|
|
|
|
var step = new DataStep( |
|
|
|
this.range.start, |
|
|
|
this.range.end, |
|
|
|
this.step = step = new DataStep( |
|
|
|
rangeStart, |
|
|
|
rangeEnd, |
|
|
|
minimumStep, |
|
|
|
this.dom.frame.offsetHeight, |
|
|
|
this.options.customRange[this.options.orientation], |
|
|
|
this.master == false && this.options.alignZeros // doess the step have to align zeros? only if not master and the options is on
|
|
|
|
this.options[this.options.orientation].range, |
|
|
|
this.master === false && this.options.alignZeros // does the step have to align zeros? only if not master and the options is on
|
|
|
|
); |
|
|
|
|
|
|
|
this.step = step; |
|
|
|
// get the distance in pixels for a step
|
|
|
|
// dead space is space that is "left over" after a step
|
|
|
|
var stepPixels = (this.dom.frame.offsetHeight - (step.deadSpace * (this.dom.frame.offsetHeight / step.marginRange))) / (((step.marginRange - step.deadSpace) / step.step)); |
|
|
|
|
|
|
|
this.stepPixels = stepPixels; |
|
|
|
|
|
|
|
var amountOfSteps = this.height / stepPixels; |
|
|
|
var stepDifference = 0; |
|
|
|
|
|
|
|
// the slave axis needs to use the same horizontal lines as the master axis.
|
|
|
|
if (this.master == false) { |
|
|
|
stepPixels = this.stepPixelsForced; |
|
|
|
stepDifference = Math.round((this.dom.frame.offsetHeight / stepPixels) - amountOfSteps); |
|
|
|
for (var i = 0; i < 0.5 * stepDifference; i++) { |
|
|
|
step.previous(); |
|
|
|
} |
|
|
|
amountOfSteps = this.height / stepPixels; |
|
|
|
|
|
|
|
if (this.zeroCrossing != -1 && this.options.alignZeros == true) { |
|
|
|
var zeroStepDifference = (step.marginEnd / step.step) - this.zeroCrossing; |
|
|
|
if (zeroStepDifference > 0) { |
|
|
|
for (var i = 0; i < zeroStepDifference; i++) {step.next();} |
|
|
|
} |
|
|
|
else if (zeroStepDifference < 0) { |
|
|
|
for (var i = 0; i < -zeroStepDifference; i++) {step.previous();} |
|
|
|
} |
|
|
|
} |
|
|
|
if (this.master === true) { |
|
|
|
this.stepPixels = ((this.dom.frame.offsetHeight) / step.marginRange) * step.step; |
|
|
|
this.amountOfSteps = Math.ceil(this.dom.frame.offsetHeight / this.stepPixels); |
|
|
|
} |
|
|
|
else { |
|
|
|
amountOfSteps += 0.25; |
|
|
|
// align with zero
|
|
|
|
if (this.options.alignZeros === true && this.zeroCrossing !== -1) { |
|
|
|
// distance is the amount of steps away from the zero crossing we are.
|
|
|
|
let distance = (step.current - this.zeroCrossing * step.step) / step.step; |
|
|
|
this.step.shift(distance); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.valueAtZero = step.marginEnd; |
|
|
|
var marginStartPos = 0; |
|
|
|
|
|
|
|
// do not draw the first label
|
|
|
|
var max = 1; |
|
|
|
// value at the bottom of the SVG
|
|
|
|
this.valueAtBottom = step.marginEnd; |
|
|
|
|
|
|
|
// Get the number of decimal places
|
|
|
|
var decimals; |
|
|
|
if(this.options.format[orientation] !== undefined) { |
|
|
|
decimals = this.options.format[orientation].decimals; |
|
|
|
if(this.options[orientation].format !== undefined) { |
|
|
|
decimals = this.options[orientation].format.decimals; |
|
|
|
} |
|
|
|
|
|
|
|
this.maxLabelSize = 0; |
|
|
|
var y = 0; |
|
|
|
while (max < Math.round(amountOfSteps)) { |
|
|
|
step.next(); |
|
|
|
y = Math.round(max * stepPixels); |
|
|
|
marginStartPos = max * stepPixels; |
|
|
|
var isMajor = step.isMajor(); |
|
|
|
|
|
|
|
if (this.options['showMinorLabels'] && isMajor == false || this.master == false && this.options['showMinorLabels'] == true) { |
|
|
|
this._redrawLabel(y - 2, step.getCurrent(decimals), orientation, 'vis-y-axis vis-minor', this.props.minorCharHeight); |
|
|
|
} |
|
|
|
var y = 0; // init value
|
|
|
|
var stepIndex = 0; // init value
|
|
|
|
var isMajor = false; // init value
|
|
|
|
while (stepIndex < this.amountOfSteps) { |
|
|
|
y = Math.round(stepIndex * this.stepPixels); |
|
|
|
isMajor = step.isMajor(); |
|
|
|
|
|
|
|
if (stepIndex > 0 && stepIndex !== this.amountOfSteps) { |
|
|
|
if (this.options['showMinorLabels'] && isMajor === false || this.master === false && this.options['showMinorLabels'] === true) { |
|
|
|
this._redrawLabel(y - 2, step.getCurrent(decimals), orientation, 'vis-y-axis vis-minor', this.props.minorCharHeight); |
|
|
|
} |
|
|
|
|
|
|
|
if (isMajor && this.options['showMajorLabels'] && this.master == true || |
|
|
|
this.options['showMinorLabels'] == false && this.master == false && isMajor == true) { |
|
|
|
if (y >= 0) { |
|
|
|
this._redrawLabel(y - 2, step.getCurrent(decimals), orientation, 'vis-y-axis vis-major', this.props.majorCharHeight); |
|
|
|
if (isMajor && this.options['showMajorLabels'] && this.master === true || |
|
|
|
this.options['showMinorLabels'] === false && this.master === false && isMajor === true) { |
|
|
|
if (y >= 0) { |
|
|
|
this._redrawLabel(y - 2, step.getCurrent(decimals), orientation, 'vis-y-axis vis-major', this.props.majorCharHeight); |
|
|
|
} |
|
|
|
this._redrawLine(y, orientation, 'vis-grid vis-horizontal vis-major', this.options.majorLinesOffset, this.props.majorLineWidth); |
|
|
|
} |
|
|
|
else { |
|
|
|
this._redrawLine(y, orientation, 'vis-grid vis-horizontal vis-minor', this.options.minorLinesOffset, this.props.minorLineWidth); |
|
|
|
} |
|
|
|
this._redrawLine(y, orientation, 'vis-grid vis-horizontal vis-major', this.options.majorLinesOffset, this.props.majorLineWidth); |
|
|
|
} |
|
|
|
else { |
|
|
|
this._redrawLine(y, orientation, 'vis-grid vis-horizontal vis-minor', this.options.minorLinesOffset, this.props.minorLineWidth); |
|
|
|
} |
|
|
|
|
|
|
|
if (this.master == true && step.current == 0) { |
|
|
|
this.zeroCrossing = max; |
|
|
|
// get zero crossing
|
|
|
|
if (this.master === true && step.current === 0) { |
|
|
|
this.zeroCrossing = stepIndex; |
|
|
|
} |
|
|
|
|
|
|
|
max++; |
|
|
|
step.next(); |
|
|
|
stepIndex += 1; |
|
|
|
} |
|
|
|
|
|
|
|
if (this.master == false) { |
|
|
|
this.conversionFactor = y / (this.valueAtZero - step.current); |
|
|
|
} |
|
|
|
else { |
|
|
|
this.conversionFactor = this.dom.frame.offsetHeight / step.marginRange; |
|
|
|
// get zero crossing if it's the last step
|
|
|
|
if (this.master === true && step.current === 0) { |
|
|
|
this.zeroCrossing = stepIndex; |
|
|
|
} |
|
|
|
|
|
|
|
this.conversionFactor = this.stepPixels / step.step; |
|
|
|
|
|
|
|
// Note that title is rotated, so we're using the height, not width!
|
|
|
|
var titleWidth = 0; |
|
|
|
if (this.options.title[orientation] !== undefined && this.options.title[orientation].text !== undefined) { |
|
|
|
if (this.options[orientation].title !== undefined && this.options[orientation].title.text !== undefined) { |
|
|
|
titleWidth = this.props.titleCharHeight; |
|
|
|
} |
|
|
|
var offset = this.options.icons == true ? Math.max(this.options.iconWidth, titleWidth) + this.options.labelOffsetX + 15 : titleWidth + this.options.labelOffsetX + 15; |
|
|
|
var offset = this.options.icons === true ? Math.max(this.options.iconWidth, titleWidth) + this.options.labelOffsetX + 15 : titleWidth + this.options.labelOffsetX + 15; |
|
|
|
|
|
|
|
// this will resize the yAxis to accommodate the labels.
|
|
|
|
if (this.maxLabelSize > (this.width - offset) && this.options.visible == true) { |
|
|
|
if (this.maxLabelSize > (this.width - offset) && this.options.visible === true) { |
|
|
|
this.width = this.maxLabelSize + offset; |
|
|
|
this.options.width = this.width + "px"; |
|
|
|
DOMutil.cleanupElements(this.DOMelements.lines); |
|
|
@ -461,7 +470,7 @@ DataAxis.prototype._redrawLabels = function () { |
|
|
|
resized = true; |
|
|
|
} |
|
|
|
// this will resize the yAxis if it is too big for the labels.
|
|
|
|
else if (this.maxLabelSize < (this.width - offset) && this.options.visible == true && this.width > this.minWidth) { |
|
|
|
else if (this.maxLabelSize < (this.width - offset) && this.options.visible === true && this.width > this.minWidth) { |
|
|
|
this.width = Math.max(this.minWidth,this.maxLabelSize + offset); |
|
|
|
this.options.width = this.width + "px"; |
|
|
|
DOMutil.cleanupElements(this.DOMelements.lines); |
|
|
@ -479,13 +488,13 @@ DataAxis.prototype._redrawLabels = function () { |
|
|
|
}; |
|
|
|
|
|
|
|
DataAxis.prototype.convertValue = function (value) { |
|
|
|
var invertedValue = this.valueAtZero - value; |
|
|
|
var invertedValue = this.valueAtBottom - value; |
|
|
|
var convertedValue = invertedValue * this.conversionFactor; |
|
|
|
return convertedValue; |
|
|
|
}; |
|
|
|
|
|
|
|
DataAxis.prototype.screenToValue = function (x) { |
|
|
|
return this.valueAtZero - (x / this.conversionFactor); |
|
|
|
return this.valueAtBottom - (x / this.conversionFactor); |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
@ -502,7 +511,7 @@ DataAxis.prototype._redrawLabel = function (y, text, orientation, className, cha |
|
|
|
var label = DOMutil.getDOMElement('div',this.DOMelements.labels, this.dom.frame); //this.dom.redundant.labels.shift();
|
|
|
|
label.className = className; |
|
|
|
label.innerHTML = text; |
|
|
|
if (orientation == 'left') { |
|
|
|
if (orientation === 'left') { |
|
|
|
label.style.left = '-' + this.options.labelOffsetX + 'px'; |
|
|
|
label.style.textAlign = "right"; |
|
|
|
} |
|
|
@ -530,12 +539,12 @@ DataAxis.prototype._redrawLabel = function (y, text, orientation, className, cha |
|
|
|
* @param width |
|
|
|
*/ |
|
|
|
DataAxis.prototype._redrawLine = function (y, orientation, className, offset, width) { |
|
|
|
if (this.master == true) { |
|
|
|
if (this.master === true) { |
|
|
|
var line = DOMutil.getDOMElement('div',this.DOMelements.lines, this.dom.lineContainer);//this.dom.redundant.lines.shift();
|
|
|
|
line.className = className; |
|
|
|
line.innerHTML = ''; |
|
|
|
|
|
|
|
if (orientation == 'left') { |
|
|
|
if (orientation === 'left') { |
|
|
|
line.style.left = (this.width - offset) + 'px'; |
|
|
|
} |
|
|
|
else { |
|
|
@ -556,17 +565,17 @@ DataAxis.prototype._redrawTitle = function (orientation) { |
|
|
|
DOMutil.prepareElements(this.DOMelements.title); |
|
|
|
|
|
|
|
// Check if the title is defined for this axes
|
|
|
|
if (this.options.title[orientation] !== undefined && this.options.title[orientation].text !== undefined) { |
|
|
|
if (this.options[orientation].title !== undefined && this.options[orientation].title.text !== undefined) { |
|
|
|
var title = DOMutil.getDOMElement('div', this.DOMelements.title, this.dom.frame); |
|
|
|
title.className = 'vis-y-axis vis-title vis-' + orientation; |
|
|
|
title.innerHTML = this.options.title[orientation].text; |
|
|
|
title.innerHTML = this.options[orientation].title.text; |
|
|
|
|
|
|
|
// Add style - if provided
|
|
|
|
if (this.options.title[orientation].style !== undefined) { |
|
|
|
util.addCssText(title, this.options.title[orientation].style); |
|
|
|
if (this.options[orientation].title.style !== undefined) { |
|
|
|
util.addCssText(title, this.options[orientation].title.style); |
|
|
|
} |
|
|
|
|
|
|
|
if (orientation == 'left') { |
|
|
|
if (orientation === 'left') { |
|
|
|
title.style.left = this.props.titleCharHeight + 'px'; |
|
|
|
} |
|
|
|
else { |
|
|
|