diff --git a/HISTORY.md b/HISTORY.md
index 8ca7c259..fcf886d0 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -11,10 +11,12 @@ http://visjs.org
### Graph2d
- Fixed round-off errors of zero on the y-axis.
+- added show major/minor lines options to dataAxis.
### Timeline
- Support for custom date formatting of the labels on the time axis.
+- added show major/minor lines options to timeline.
## 2014-12-09, version 3.7.2
diff --git a/dist/vis.js b/dist/vis.js
index efbe3065..4bbeb840 100644
--- a/dist/vis.js
+++ b/dist/vis.js
@@ -106,7 +106,7 @@ return /******/ (function(modules) { // webpackBootstrap
exports.Graph2d = __webpack_require__(42);
exports.timeline = {
DateUtil: __webpack_require__(24),
- DataStep: __webpack_require__(44),
+ DataStep: __webpack_require__(50),
Range: __webpack_require__(21),
stack: __webpack_require__(28),
TimeStep: __webpack_require__(38),
@@ -123,12 +123,12 @@ return /******/ (function(modules) { // webpackBootstrap
Component: __webpack_require__(23),
CurrentTime: __webpack_require__(39),
CustomTime: __webpack_require__(41),
- DataAxis: __webpack_require__(45),
- GraphGroup: __webpack_require__(46),
+ DataAxis: __webpack_require__(44),
+ GraphGroup: __webpack_require__(45),
Group: __webpack_require__(27),
BackgroundGroup: __webpack_require__(31),
ItemSet: __webpack_require__(26),
- Legend: __webpack_require__(50),
+ Legend: __webpack_require__(49),
LineGraph: __webpack_require__(43),
TimeAxis: __webpack_require__(37)
}
@@ -18069,6 +18069,8 @@ return /******/ (function(modules) { // webpackBootstrap
// TODO: implement timeaxis orientations 'left' and 'right'
showMinorLabels: true,
showMajorLabels: true,
+ showMajorLines: true,
+ showMinorLines: true,
format: null
};
this.options = util.extend({}, this.defaultOptions);
@@ -18094,7 +18096,7 @@ return /******/ (function(modules) { // webpackBootstrap
TimeAxis.prototype.setOptions = function(options) {
if (options) {
// copy all options that we know
- util.selectiveExtend(['orientation', 'showMinorLabels', 'showMajorLabels','hiddenDates', 'format'], this.options, options);
+ util.selectiveExtend(['orientation', 'showMinorLabels', 'showMajorLabels', 'showMinorLines', 'showMajorLines','hiddenDates', 'format'], this.options, options);
// apply locale to moment.js
// TODO: not so nice, this is applied globally to moment.js
@@ -18253,9 +18255,11 @@ return /******/ (function(modules) { // webpackBootstrap
}
this._repaintMajorText(x, step.getLabelMajor(), orientation);
}
- this._repaintMajorLine(x, orientation);
+ if (this.options.showMajorLines == true) {
+ this._repaintMajorLine(x, orientation);
+ }
}
- else {
+ else if (this.options.showMinorLines == true) {
this._repaintMinorLine(x, orientation);
}
@@ -19631,10 +19635,10 @@ return /******/ (function(modules) { // webpackBootstrap
var DataSet = __webpack_require__(7);
var DataView = __webpack_require__(9);
var Component = __webpack_require__(23);
- var DataAxis = __webpack_require__(45);
- var GraphGroup = __webpack_require__(46);
- var Legend = __webpack_require__(50);
- var BarGraphFunctions = __webpack_require__(49);
+ var DataAxis = __webpack_require__(44);
+ var GraphGroup = __webpack_require__(45);
+ var Legend = __webpack_require__(49);
+ var BarGraphFunctions = __webpack_require__(48);
var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items
@@ -19678,6 +19682,8 @@ return /******/ (function(modules) { // webpackBootstrap
dataAxis: {
showMinorLabels: true,
showMajorLabels: true,
+ showMinorLines: true,
+ showMajorLines: true,
icons: false,
width: '40px',
visible: true,
@@ -20618,582 +20624,305 @@ return /******/ (function(modules) { // webpackBootstrap
/* 44 */
/***/ function(module, exports, __webpack_require__) {
+ var util = __webpack_require__(1);
+ var DOMutil = __webpack_require__(6);
+ var Component = __webpack_require__(23);
+ var DataStep = __webpack_require__(50);
+
/**
- * @constructor DataStep
- * The class DataStep is an iterator for data for the lineGraph. You provide a start data point and an
- * end data point. The class itself determines the best scale (step size) based on the
- * provided start Date, end Date, and minimumStep.
- *
- * If minimumStep is provided, the step size is chosen as close as possible
- * to the minimumStep but larger than minimumStep. If minimumStep is not
- * provided, the scale is set to 1 DAY.
- * The minimumStep should correspond with the onscreen size of about 6 characters
- *
- * Alternatively, you can set a scale by hand.
- * After creation, you can initialize the class by executing first(). Then you
- * can iterate from the start date to the end date via next(). You can check if
- * the end date is reached with the function hasNext(). After each step, you can
- * retrieve the current date via getCurrent().
- * The DataStep has scales ranging from milliseconds, seconds, minutes, hours,
- * days, to years.
- *
- * Version: 1.2
- *
- * @param {Date} [start] The start date, for example new Date(2010, 9, 21)
- * or new Date(2010, 9, 21, 23, 45, 00)
- * @param {Date} [end] The end date
- * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds
+ * A horizontal time axis
+ * @param {Object} [options] See DataAxis.setOptions for the available
+ * options.
+ * @constructor DataAxis
+ * @extends Component
+ * @param body
*/
- function DataStep(start, end, minimumStep, containerHeight, customRange, alignZeros) {
- // variables
- this.current = 0;
+ function DataAxis (body, options, svg, linegraphOptions) {
+ this.id = util.randomUUID();
+ this.body = body;
- this.autoScale = true;
- this.stepIndex = 0;
- this.step = 1;
- this.scale = 1;
+ this.defaultOptions = {
+ orientation: 'left', // supported: 'left', 'right'
+ showMinorLabels: true,
+ showMajorLabels: true,
+ showMinorLines: true,
+ showMajorLines: true,
+ icons: true,
+ majorLinesOffset: 7,
+ minorLinesOffset: 4,
+ labelOffsetX: 10,
+ labelOffsetY: 2,
+ iconWidth: 20,
+ width: '40px',
+ visible: true,
+ alignZeros: true,
+ customRange: {
+ left: {min:undefined, max:undefined},
+ right: {min:undefined, max:undefined}
+ },
+ title: {
+ left: {text:undefined},
+ right: {text:undefined}
+ },
+ format: {
+ left: {decimals: undefined},
+ right: {decimals: undefined}
+ }
+ };
- this.marginStart;
- this.marginEnd;
- this.deadSpace = 0;
+ this.linegraphOptions = linegraphOptions;
+ this.linegraphSVG = svg;
+ this.props = {};
+ this.DOMelements = { // dynamic elements
+ lines: {},
+ labels: {},
+ title: {}
+ };
- this.majorSteps = [1, 2, 5, 10];
- this.minorSteps = [0.25, 0.5, 1, 2];
+ this.dom = {};
- this.alignZeros = alignZeros;
+ this.range = {start:0, end:0};
- this.setRange(start, end, minimumStep, containerHeight, customRange);
- }
+ this.options = util.extend({}, this.defaultOptions);
+ this.conversionFactor = 1;
+ this.setOptions(options);
+ this.width = Number(('' + this.options.width).replace("px",""));
+ this.minWidth = this.width;
+ this.height = this.linegraphSVG.offsetHeight;
+ this.hidden = false;
+ this.stepPixels = 25;
+ this.stepPixelsForced = 25;
+ this.zeroCrossing = -1;
- /**
- * Set a new range
- * If minimumStep is provided, the step size is chosen as close as possible
- * to the minimumStep but larger than minimumStep. If minimumStep is not
- * provided, the scale is set to 1 DAY.
- * The minimumStep should correspond with the onscreen size of about 6 characters
- * @param {Number} [start] The start date and time.
- * @param {Number} [end] The end date and time.
- * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds
- */
- DataStep.prototype.setRange = function(start, end, minimumStep, containerHeight, customRange) {
- this._start = customRange.min === undefined ? start : customRange.min;
- this._end = customRange.max === undefined ? end : customRange.max;
+ this.lineOffset = 0;
+ this.master = true;
+ this.svgElements = {};
+ this.iconsRemoved = false;
- if (this._start == this._end) {
- this._start -= 0.75;
- this._end += 1;
- }
- if (this.autoScale == true) {
- this.setMinimumStep(minimumStep, containerHeight);
- }
+ this.groups = {};
+ this.amountOfGroups = 0;
- this.setFirst(customRange);
- };
+ // create the HTML DOM
+ this._create();
- /**
- * Automatically determine the scale that bests fits the provided minimum step
- * @param {Number} [minimumStep] The minimum step size in milliseconds
- */
- DataStep.prototype.setMinimumStep = function(minimumStep, containerHeight) {
- // round to floor
- var size = this._end - this._start;
- var safeSize = size * 1.2;
- var minimumStepValue = minimumStep * (safeSize / containerHeight);
- var orderOfMagnitude = Math.round(Math.log(safeSize)/Math.LN10);
+ var me = this;
+ this.body.emitter.on("verticalDrag", function() {
+ me.dom.lineContainer.style.top = me.body.domProps.scrollTop + 'px';
+ });
+ }
- var minorStepIdx = -1;
- var magnitudefactor = Math.pow(10,orderOfMagnitude);
+ DataAxis.prototype = new Component();
- var start = 0;
- if (orderOfMagnitude < 0) {
- start = orderOfMagnitude;
- }
- var solutionFound = false;
- for (var i = start; Math.abs(i) <= Math.abs(orderOfMagnitude); i++) {
- magnitudefactor = Math.pow(10,i);
- for (var j = 0; j < this.minorSteps.length; j++) {
- var stepSize = magnitudefactor * this.minorSteps[j];
- if (stepSize >= minimumStepValue) {
- solutionFound = true;
- minorStepIdx = j;
- break;
- }
- }
- if (solutionFound == true) {
- break;
- }
+ DataAxis.prototype.addGroup = function(label, graphOptions) {
+ if (!this.groups.hasOwnProperty(label)) {
+ this.groups[label] = graphOptions;
}
- this.stepIndex = minorStepIdx;
- this.scale = magnitudefactor;
- this.step = magnitudefactor * this.minorSteps[minorStepIdx];
+ this.amountOfGroups += 1;
};
+ DataAxis.prototype.updateGroup = function(label, graphOptions) {
+ this.groups[label] = graphOptions;
+ };
-
- /**
- * Round the current date to the first minor date value
- * This must be executed once when the current date is set to start Date
- */
- DataStep.prototype.setFirst = function(customRange) {
- if (customRange === undefined) {
- customRange = {};
- }
-
- var niceStart = customRange.min === undefined ? this._start - (this.scale * 2 * this.minorSteps[this.stepIndex]) : customRange.min;
- var niceEnd = customRange.max === undefined ? this._end + (this.scale * this.minorSteps[this.stepIndex]) : customRange.max;
-
- this.marginEnd = customRange.max === undefined ? this.roundToMinor(niceEnd) : customRange.max;
- this.marginStart = customRange.min === undefined ? this.roundToMinor(niceStart) : customRange.min;
-
- // if we need to align the zero's we need to make sure that there is a zero to use.
- if (this.alignZeros == true && (this.marginEnd - this.marginStart) % this.step != 0) {
- this.marginEnd += this.marginEnd % this.step;
+ DataAxis.prototype.removeGroup = function(label) {
+ if (this.groups.hasOwnProperty(label)) {
+ delete this.groups[label];
+ this.amountOfGroups -= 1;
}
+ };
- this.deadSpace = this.roundToMinor(niceEnd) - niceEnd + this.roundToMinor(niceStart) - niceStart;
- this.marginRange = this.marginEnd - this.marginStart;
+ DataAxis.prototype.setOptions = function (options) {
+ if (options) {
+ var redraw = false;
+ if (this.options.orientation != options.orientation && options.orientation !== undefined) {
+ redraw = true;
+ }
+ var fields = [
+ 'orientation',
+ 'showMinorLabels',
+ 'showMajorLabels',
+ 'showMajorLines',
+ 'showMinorLines',
+ 'icons',
+ 'majorLinesOffset',
+ 'minorLinesOffset',
+ 'labelOffsetX',
+ 'labelOffsetY',
+ 'iconWidth',
+ 'width',
+ 'visible',
+ 'customRange',
+ 'title',
+ 'format',
+ 'alignZeros'
+ ];
+ util.selectiveExtend(fields, this.options, options);
- this.current = this.marginEnd;
- };
+ this.minWidth = Number(('' + this.options.width).replace("px",""));
- DataStep.prototype.roundToMinor = function(value) {
- var rounded = value - (value % (this.scale * this.minorSteps[this.stepIndex]));
- if (value % (this.scale * this.minorSteps[this.stepIndex]) > 0.5 * (this.scale * this.minorSteps[this.stepIndex])) {
- return rounded + (this.scale * this.minorSteps[this.stepIndex]);
- }
- else {
- return rounded;
+ if (redraw == true && this.dom.frame) {
+ this.hide();
+ this.show();
+ }
}
- }
+ };
/**
- * Check if the there is a next step
- * @return {boolean} true if the current date has not passed the end date
+ * Create the HTML DOM for the DataAxis
*/
- DataStep.prototype.hasNext = function () {
- return (this.current >= this.marginStart);
- };
+ DataAxis.prototype._create = function() {
+ this.dom.frame = document.createElement('div');
+ this.dom.frame.style.width = this.options.width;
+ this.dom.frame.style.height = this.height;
- /**
- * Do the next step
- */
- DataStep.prototype.next = function() {
- var prev = this.current;
- this.current -= this.step;
-
- // safety mechanism: if current time is still unchanged, move to the end
- if (this.current == prev) {
- this.current = this._end;
- }
- };
+ this.dom.lineContainer = document.createElement('div');
+ this.dom.lineContainer.style.width = '100%';
+ this.dom.lineContainer.style.height = this.height;
+ this.dom.lineContainer.style.position = 'relative';
- /**
- * Do the next step
- */
- DataStep.prototype.previous = function() {
- this.current += this.step;
- this.marginEnd += this.step;
- this.marginRange = this.marginEnd - this.marginStart;
+ // create svg element for graph drawing.
+ this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg");
+ this.svg.style.position = "absolute";
+ this.svg.style.top = '0px';
+ this.svg.style.height = '100%';
+ this.svg.style.width = '100%';
+ this.svg.style.display = "block";
+ this.dom.frame.appendChild(this.svg);
};
+ DataAxis.prototype._redrawGroupIcons = function () {
+ DOMutil.prepareElements(this.svgElements);
+ var x;
+ var iconWidth = this.options.iconWidth;
+ var iconHeight = 15;
+ var iconOffset = 4;
+ var y = iconOffset + 0.5 * iconHeight;
- /**
- * Get the current datetime
- * @return {String} current The current date
- */
- DataStep.prototype.getCurrent = function(decimals) {
- // prevent round-off errors when close to zero
- var current = (Math.abs(this.current) < this.step / 2) ? 0 : this.current;
- var toPrecision = '' + Number(current).toPrecision(5);
-
- // If decimals is specified, then limit or extend the string as required
- if(decimals !== undefined && !isNaN(Number(decimals))) {
- // If string includes exponent, then we need to add it to the end
- var exp = "";
- var index = toPrecision.indexOf("e");
- if(index != -1) {
- // Get the exponent
- exp = toPrecision.slice(index);
- // Remove the exponent in case we need to zero-extend
- toPrecision = toPrecision.slice(0, index);
- }
- index = Math.max(toPrecision.indexOf(","), toPrecision.indexOf("."));
- if(index === -1) {
- // No decimal found - if we want decimals, then we need to add it
- if(decimals !== 0) {
- toPrecision += '.';
- }
- // Calculate how long the string should be
- index = toPrecision.length + decimals;
- }
- else if(decimals !== 0) {
- // Calculate how long the string should be - accounting for the decimal place
- index += decimals + 1;
- }
- if(index > toPrecision.length) {
- // We need to add zeros!
- for(var cnt = index - toPrecision.length; cnt > 0; cnt--) {
- toPrecision += '0';
- }
- }
- else {
- // we need to remove characters
- toPrecision = toPrecision.slice(0, index);
- }
- // Add the exponent if there is one
- toPrecision += exp;
+ if (this.options.orientation == 'left') {
+ x = iconOffset;
}
else {
- if (toPrecision.indexOf(",") != -1 || toPrecision.indexOf(".") != -1) {
- // If no decimal is specified, and there are decimal places, remove trailing zeros
- for (var i = toPrecision.length - 1; i > 0; i--) {
- if (toPrecision[i] == "0") {
- toPrecision = toPrecision.slice(0, i);
- }
- else if (toPrecision[i] == "." || toPrecision[i] == ",") {
- toPrecision = toPrecision.slice(0, i);
- break;
- }
- else {
- break;
- }
+ 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;
}
}
}
- return toPrecision;
+ DOMutil.cleanupElements(this.svgElements);
+ this.iconsRemoved = false;
};
-
+ DataAxis.prototype._cleanupIcons = function() {
+ if (this.iconsRemoved == false) {
+ DOMutil.prepareElements(this.svgElements);
+ DOMutil.cleanupElements(this.svgElements);
+ this.iconsRemoved = true;
+ }
+ }
/**
- * Snap a date to a rounded value.
- * The snap intervals are dependent on the current scale and step.
- * @param {Date} date the date to be snapped.
- * @return {Date} snappedDate
+ * Create the HTML DOM for the DataAxis
*/
- DataStep.prototype.snap = function(date) {
+ DataAxis.prototype.show = function() {
+ this.hidden = false;
+ if (!this.dom.frame.parentNode) {
+ if (this.options.orientation == 'left') {
+ this.body.dom.left.appendChild(this.dom.frame);
+ }
+ else {
+ this.body.dom.right.appendChild(this.dom.frame);
+ }
+ }
+ if (!this.dom.lineContainer.parentNode) {
+ this.body.dom.backgroundHorizontal.appendChild(this.dom.lineContainer);
+ }
};
/**
- * Check if the current value is a major value (for example when the step
- * is DAY, a major value is each first day of the MONTH)
- * @return {boolean} true if current date is major, else false.
+ * Create the HTML DOM for the DataAxis
*/
- DataStep.prototype.isMajor = function() {
- return (this.current % (this.scale * this.majorSteps[this.stepIndex]) == 0);
- };
-
- module.exports = DataStep;
-
+ DataAxis.prototype.hide = function() {
+ this.hidden = true;
+ if (this.dom.frame.parentNode) {
+ this.dom.frame.parentNode.removeChild(this.dom.frame);
+ }
-/***/ },
-/* 45 */
-/***/ function(module, exports, __webpack_require__) {
+ if (this.dom.lineContainer.parentNode) {
+ this.dom.lineContainer.parentNode.removeChild(this.dom.lineContainer);
+ }
+ };
- var util = __webpack_require__(1);
- var DOMutil = __webpack_require__(6);
- var Component = __webpack_require__(23);
- var DataStep = __webpack_require__(44);
+ /**
+ * Set a range (start and end)
+ * @param end
+ * @param start
+ * @param end
+ */
+ DataAxis.prototype.setRange = function (start, end) {
+ if (this.master == false && this.options.alignZeros == true && this.zeroCrossing != -1) {
+ if (start > 0) {
+ start = 0;
+ }
+ }
+ this.range.start = start;
+ this.range.end = end;
+ };
/**
- * A horizontal time axis
- * @param {Object} [options] See DataAxis.setOptions for the available
- * options.
- * @constructor DataAxis
- * @extends Component
- * @param body
+ * Repaint the component
+ * @return {boolean} Returns true if the component is resized
*/
- function DataAxis (body, options, svg, linegraphOptions) {
- this.id = util.randomUUID();
- this.body = body;
+ DataAxis.prototype.redraw = function () {
+ var changeCalled = false;
+ var activeGroups = 0;
+
+ // Make sure the line container adheres to the vertical scrolling.
+ this.dom.lineContainer.style.top = this.body.domProps.scrollTop + 'px';
- this.defaultOptions = {
- orientation: 'left', // supported: 'left', 'right'
- showMinorLabels: true,
- showMajorLabels: true,
- icons: true,
- majorLinesOffset: 7,
- minorLinesOffset: 4,
- labelOffsetX: 10,
- labelOffsetY: 2,
- iconWidth: 20,
- width: '40px',
- visible: true,
- alignZeros: true,
- customRange: {
- left: {min:undefined, max:undefined},
- right: {min:undefined, max:undefined}
- },
- title: {
- left: {text:undefined},
- right: {text:undefined}
- },
- format: {
- left: {decimals: undefined},
- right: {decimals: undefined}
+ 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)) {
+ activeGroups++;
+ }
}
- };
+ }
+ if (this.amountOfGroups == 0 || activeGroups == 0) {
+ this.hide();
+ }
+ else {
+ this.show();
+ this.height = Number(this.linegraphSVG.style.height.replace("px",""));
- this.linegraphOptions = linegraphOptions;
- this.linegraphSVG = svg;
- this.props = {};
- this.DOMelements = { // dynamic elements
- lines: {},
- labels: {},
- title: {}
- };
+ // 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.dom = {};
+ var props = this.props;
+ var frame = this.dom.frame;
- this.range = {start:0, end:0};
+ // update classname
+ frame.className = 'dataaxis';
- this.options = util.extend({}, this.defaultOptions);
- this.conversionFactor = 1;
+ // calculate character width and height
+ this._calculateCharSize();
- this.setOptions(options);
- this.width = Number(('' + this.options.width).replace("px",""));
- this.minWidth = this.width;
- this.height = this.linegraphSVG.offsetHeight;
- this.hidden = false;
-
- this.stepPixels = 25;
- this.stepPixelsForced = 25;
- this.zeroCrossing = -1;
-
- this.lineOffset = 0;
- this.master = true;
- this.svgElements = {};
- this.iconsRemoved = false;
-
-
- this.groups = {};
- this.amountOfGroups = 0;
-
- // create the HTML DOM
- this._create();
-
- var me = this;
- this.body.emitter.on("verticalDrag", function() {
- me.dom.lineContainer.style.top = me.body.domProps.scrollTop + 'px';
- });
- }
-
- DataAxis.prototype = new Component();
-
-
- DataAxis.prototype.addGroup = function(label, graphOptions) {
- if (!this.groups.hasOwnProperty(label)) {
- this.groups[label] = graphOptions;
- }
- this.amountOfGroups += 1;
- };
-
- DataAxis.prototype.updateGroup = function(label, graphOptions) {
- this.groups[label] = graphOptions;
- };
-
- DataAxis.prototype.removeGroup = function(label) {
- if (this.groups.hasOwnProperty(label)) {
- delete this.groups[label];
- this.amountOfGroups -= 1;
- }
- };
-
-
- DataAxis.prototype.setOptions = function (options) {
- if (options) {
- var redraw = false;
- if (this.options.orientation != options.orientation && options.orientation !== undefined) {
- redraw = true;
- }
- var fields = [
- 'orientation',
- 'showMinorLabels',
- 'showMajorLabels',
- 'icons',
- 'majorLinesOffset',
- 'minorLinesOffset',
- 'labelOffsetX',
- 'labelOffsetY',
- 'iconWidth',
- 'width',
- 'visible',
- 'customRange',
- 'title',
- 'format',
- 'alignZeros'
- ];
- util.selectiveExtend(fields, this.options, options);
-
- this.minWidth = Number(('' + this.options.width).replace("px",""));
-
- if (redraw == true && this.dom.frame) {
- this.hide();
- this.show();
- }
- }
- };
-
-
- /**
- * Create the HTML DOM for the DataAxis
- */
- DataAxis.prototype._create = function() {
- this.dom.frame = document.createElement('div');
- this.dom.frame.style.width = this.options.width;
- this.dom.frame.style.height = this.height;
-
- this.dom.lineContainer = document.createElement('div');
- this.dom.lineContainer.style.width = '100%';
- this.dom.lineContainer.style.height = this.height;
- this.dom.lineContainer.style.position = 'relative';
-
- // create svg element for graph drawing.
- this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg");
- this.svg.style.position = "absolute";
- this.svg.style.top = '0px';
- this.svg.style.height = '100%';
- this.svg.style.width = '100%';
- this.svg.style.display = "block";
- this.dom.frame.appendChild(this.svg);
- };
-
- DataAxis.prototype._redrawGroupIcons = function () {
- DOMutil.prepareElements(this.svgElements);
-
- var x;
- var iconWidth = this.options.iconWidth;
- var iconHeight = 15;
- var iconOffset = 4;
- var y = iconOffset + 0.5 * iconHeight;
-
- 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;
- }
- }
- }
-
- DOMutil.cleanupElements(this.svgElements);
- this.iconsRemoved = false;
- };
-
- DataAxis.prototype._cleanupIcons = function() {
- if (this.iconsRemoved == false) {
- DOMutil.prepareElements(this.svgElements);
- DOMutil.cleanupElements(this.svgElements);
- this.iconsRemoved = true;
- }
- }
-
- /**
- * Create the HTML DOM for the DataAxis
- */
- DataAxis.prototype.show = function() {
- this.hidden = false;
- if (!this.dom.frame.parentNode) {
- if (this.options.orientation == 'left') {
- this.body.dom.left.appendChild(this.dom.frame);
- }
- else {
- this.body.dom.right.appendChild(this.dom.frame);
- }
- }
-
- if (!this.dom.lineContainer.parentNode) {
- this.body.dom.backgroundHorizontal.appendChild(this.dom.lineContainer);
- }
- };
-
- /**
- * Create the HTML DOM for the DataAxis
- */
- DataAxis.prototype.hide = function() {
- this.hidden = true;
- if (this.dom.frame.parentNode) {
- this.dom.frame.parentNode.removeChild(this.dom.frame);
- }
-
- if (this.dom.lineContainer.parentNode) {
- this.dom.lineContainer.parentNode.removeChild(this.dom.lineContainer);
- }
- };
-
- /**
- * Set a range (start and end)
- * @param end
- * @param start
- * @param end
- */
- DataAxis.prototype.setRange = function (start, end) {
- if (this.master == false && this.options.alignZeros == true && this.zeroCrossing != -1) {
- if (start > 0) {
- start = 0;
- }
- }
- this.range.start = start;
- this.range.end = end;
- };
-
- /**
- * Repaint the component
- * @return {boolean} Returns true if the component is resized
- */
- DataAxis.prototype.redraw = function () {
- var changeCalled = false;
- var activeGroups = 0;
-
- // Make sure the line container adheres to the vertical scrolling.
- this.dom.lineContainer.style.top = this.body.domProps.scrollTop + 'px';
-
- 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)) {
- activeGroups++;
- }
- }
- }
- if (this.amountOfGroups == 0 || activeGroups == 0) {
- this.hide();
- }
- else {
- this.show();
- this.height = Number(this.linegraphSVG.style.height.replace("px",""));
-
- // 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;
-
- var props = this.props;
- var frame = this.dom.frame;
-
- // update classname
- frame.className = 'dataaxis';
-
- // calculate character width and height
- this._calculateCharSize();
-
- var orientation = this.options.orientation;
- var showMinorLabels = this.options.showMinorLabels;
- var showMajorLabels = this.options.showMajorLabels;
+ var orientation = this.options.orientation;
+ var showMinorLabels = this.options.showMinorLabels;
+ var showMajorLabels = this.options.showMajorLabels;
// determine the width and height of the elements for the axis
props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0;
@@ -21318,9 +21047,11 @@ return /******/ (function(modules) { // webpackBootstrap
if (y >= 0) {
this._redrawLabel(y - 2, step.getCurrent(decimals), orientation, 'yAxis major', this.props.majorCharHeight);
}
- this._redrawLine(y, orientation, 'grid horizontal major', this.options.majorLinesOffset, this.props.majorLineWidth);
+ if (this.options.showMajorLines == true) {
+ this._redrawLine(y, orientation, 'grid horizontal major', this.options.majorLinesOffset, this.props.majorLineWidth);
+ }
}
- else {
+ else if (this.options.showMinorLines == true) {
this._redrawLine(y, orientation, 'grid horizontal minor', this.options.minorLinesOffset, this.props.minorLineWidth);
}
@@ -21532,14 +21263,14 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 46 */
+/* 45 */
/***/ function(module, exports, __webpack_require__) {
var util = __webpack_require__(1);
var DOMutil = __webpack_require__(6);
- var Line = __webpack_require__(47);
- var Bar = __webpack_require__(49);
- var Points = __webpack_require__(48);
+ var Line = __webpack_require__(46);
+ var Bar = __webpack_require__(48);
+ var Points = __webpack_require__(47);
/**
* /**
@@ -21737,14 +21468,14 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 47 */
+/* 46 */
/***/ function(module, exports, __webpack_require__) {
/**
* Created by Alex on 11/11/2014.
*/
var DOMutil = __webpack_require__(6);
- var Points = __webpack_require__(48);
+ var Points = __webpack_require__(47);
function Line(groupId, options) {
this.groupId = groupId;
@@ -21961,7 +21692,7 @@ return /******/ (function(modules) { // webpackBootstrap
/***/ },
-/* 48 */
+/* 47 */
/***/ function(module, exports, __webpack_require__) {
/**
@@ -22009,14 +21740,14 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = Points;
/***/ },
-/* 49 */
+/* 48 */
/***/ function(module, exports, __webpack_require__) {
/**
* Created by Alex on 11/11/2014.
*/
var DOMutil = __webpack_require__(6);
- var Points = __webpack_require__(48);
+ var Points = __webpack_require__(47);
function Bargraph(groupId, options) {
this.groupId = groupId;
@@ -22243,7 +21974,7 @@ return /******/ (function(modules) { // webpackBootstrap
module.exports = Bargraph;
/***/ },
-/* 50 */
+/* 49 */
/***/ function(module, exports, __webpack_require__) {
var util = __webpack_require__(1);
@@ -22273,183 +22004,464 @@ return /******/ (function(modules) { // webpackBootstrap
this.options = util.extend({},this.defaultOptions);
this.linegraphOptions = linegraphOptions;
- this.svgElements = {};
- this.dom = {};
- this.groups = {};
- this.amountOfGroups = 0;
- this._create();
+ this.svgElements = {};
+ this.dom = {};
+ this.groups = {};
+ this.amountOfGroups = 0;
+ this._create();
+
+ this.setOptions(options);
+ }
+
+ Legend.prototype = new Component();
+
+ Legend.prototype.clear = function() {
+ this.groups = {};
+ this.amountOfGroups = 0;
+ }
+
+ Legend.prototype.addGroup = function(label, graphOptions) {
+
+ if (!this.groups.hasOwnProperty(label)) {
+ this.groups[label] = graphOptions;
+ }
+ this.amountOfGroups += 1;
+ };
+
+ Legend.prototype.updateGroup = function(label, graphOptions) {
+ this.groups[label] = graphOptions;
+ };
+
+ Legend.prototype.removeGroup = function(label) {
+ if (this.groups.hasOwnProperty(label)) {
+ delete this.groups[label];
+ this.amountOfGroups -= 1;
+ }
+ };
+
+ Legend.prototype._create = function() {
+ this.dom.frame = document.createElement('div');
+ this.dom.frame.className = 'legend';
+ this.dom.frame.style.position = "absolute";
+ this.dom.frame.style.top = "10px";
+ this.dom.frame.style.display = "block";
+
+ this.dom.textArea = document.createElement('div');
+ this.dom.textArea.className = 'legendText';
+ this.dom.textArea.style.position = "relative";
+ this.dom.textArea.style.top = "0px";
+
+ this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg");
+ this.svg.style.position = 'absolute';
+ this.svg.style.top = 0 +'px';
+ this.svg.style.width = this.options.iconSize + 5 + 'px';
+ this.svg.style.height = '100%';
+
+ this.dom.frame.appendChild(this.svg);
+ this.dom.frame.appendChild(this.dom.textArea);
+ };
+
+ /**
+ * Hide the component from the DOM
+ */
+ Legend.prototype.hide = function() {
+ // remove the frame containing the items
+ if (this.dom.frame.parentNode) {
+ this.dom.frame.parentNode.removeChild(this.dom.frame);
+ }
+ };
+
+ /**
+ * Show the component in the DOM (when not already visible).
+ * @return {Boolean} changed
+ */
+ Legend.prototype.show = function() {
+ // show frame containing the items
+ if (!this.dom.frame.parentNode) {
+ this.body.dom.center.appendChild(this.dom.frame);
+ }
+ };
+
+ Legend.prototype.setOptions = function(options) {
+ var fields = ['enabled','orientation','icons','left','right'];
+ util.selectiveDeepExtend(fields, this.options, options);
+ };
+
+ Legend.prototype.redraw = function() {
+ var activeGroups = 0;
+ 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)) {
+ activeGroups++;
+ }
+ }
+ }
+
+ if (this.options[this.side].visible == false || this.amountOfGroups == 0 || this.options.enabled == false || activeGroups == 0) {
+ this.hide();
+ }
+ else {
+ this.show();
+ if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'bottom-left') {
+ this.dom.frame.style.left = '4px';
+ this.dom.frame.style.textAlign = "left";
+ this.dom.textArea.style.textAlign = "left";
+ this.dom.textArea.style.left = (this.options.iconSize + 15) + 'px';
+ this.dom.textArea.style.right = '';
+ this.svg.style.left = 0 +'px';
+ this.svg.style.right = '';
+ }
+ else {
+ this.dom.frame.style.right = '4px';
+ this.dom.frame.style.textAlign = "right";
+ this.dom.textArea.style.textAlign = "right";
+ this.dom.textArea.style.right = (this.options.iconSize + 15) + 'px';
+ this.dom.textArea.style.left = '';
+ this.svg.style.right = 0 +'px';
+ this.svg.style.left = '';
+ }
+
+ if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'top-right') {
+ this.dom.frame.style.top = 4 - Number(this.body.dom.center.style.top.replace("px","")) + 'px';
+ this.dom.frame.style.bottom = '';
+ }
+ else {
+ var scrollableHeight = this.body.domProps.center.height - this.body.domProps.centerContainer.height;
+ this.dom.frame.style.bottom = 4 + scrollableHeight + Number(this.body.dom.center.style.top.replace("px","")) + 'px';
+ this.dom.frame.style.top = '';
+ }
+
+ if (this.options.icons == false) {
+ this.dom.frame.style.width = this.dom.textArea.offsetWidth + 10 + 'px';
+ this.dom.textArea.style.right = '';
+ this.dom.textArea.style.left = '';
+ this.svg.style.width = '0px';
+ }
+ else {
+ this.dom.frame.style.width = this.options.iconSize + 15 + this.dom.textArea.offsetWidth + 10 + 'px'
+ this.drawLegendIcons();
+ }
+
+ var content = '';
+ 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)) {
+ content += this.groups[groupId].content + '
';
+ }
+ }
+ }
+ this.dom.textArea.innerHTML = content;
+ this.dom.textArea.style.lineHeight = ((0.75 * this.options.iconSize) + this.options.iconSpacing) + 'px';
+ }
+ };
+
+ Legend.prototype.drawLegendIcons = function() {
+ if (this.dom.frame.parentNode) {
+ DOMutil.prepareElements(this.svgElements);
+ var padding = window.getComputedStyle(this.dom.frame).paddingTop;
+ var iconOffset = Number(padding.replace('px',''));
+ var x = iconOffset;
+ var iconWidth = this.options.iconSize;
+ var iconHeight = 0.75 * this.options.iconSize;
+ var y = iconOffset + 0.5 * iconHeight + 3;
+
+ this.svg.style.width = iconWidth + 5 + iconOffset + 'px';
+
+ 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 + this.options.iconSpacing;
+ }
+ }
+ }
+
+ DOMutil.cleanupElements(this.svgElements);
+ }
+ };
+
+ module.exports = Legend;
+
+
+/***/ },
+/* 50 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * @constructor DataStep
+ * The class DataStep is an iterator for data for the lineGraph. You provide a start data point and an
+ * end data point. The class itself determines the best scale (step size) based on the
+ * provided start Date, end Date, and minimumStep.
+ *
+ * If minimumStep is provided, the step size is chosen as close as possible
+ * to the minimumStep but larger than minimumStep. If minimumStep is not
+ * provided, the scale is set to 1 DAY.
+ * The minimumStep should correspond with the onscreen size of about 6 characters
+ *
+ * Alternatively, you can set a scale by hand.
+ * After creation, you can initialize the class by executing first(). Then you
+ * can iterate from the start date to the end date via next(). You can check if
+ * the end date is reached with the function hasNext(). After each step, you can
+ * retrieve the current date via getCurrent().
+ * The DataStep has scales ranging from milliseconds, seconds, minutes, hours,
+ * days, to years.
+ *
+ * Version: 1.2
+ *
+ * @param {Date} [start] The start date, for example new Date(2010, 9, 21)
+ * or new Date(2010, 9, 21, 23, 45, 00)
+ * @param {Date} [end] The end date
+ * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds
+ */
+ function DataStep(start, end, minimumStep, containerHeight, customRange, alignZeros) {
+ // variables
+ this.current = 0;
+
+ this.autoScale = true;
+ this.stepIndex = 0;
+ this.step = 1;
+ this.scale = 1;
+
+ this.marginStart;
+ this.marginEnd;
+ this.deadSpace = 0;
+
+ this.majorSteps = [1, 2, 5, 10];
+ this.minorSteps = [0.25, 0.5, 1, 2];
+
+ this.alignZeros = alignZeros;
+
+ this.setRange(start, end, minimumStep, containerHeight, customRange);
+ }
+
+
+
+ /**
+ * Set a new range
+ * If minimumStep is provided, the step size is chosen as close as possible
+ * to the minimumStep but larger than minimumStep. If minimumStep is not
+ * provided, the scale is set to 1 DAY.
+ * The minimumStep should correspond with the onscreen size of about 6 characters
+ * @param {Number} [start] The start date and time.
+ * @param {Number} [end] The end date and time.
+ * @param {Number} [minimumStep] Optional. Minimum step size in milliseconds
+ */
+ DataStep.prototype.setRange = function(start, end, minimumStep, containerHeight, customRange) {
+ this._start = customRange.min === undefined ? start : customRange.min;
+ this._end = customRange.max === undefined ? end : customRange.max;
+
+ if (this._start == this._end) {
+ this._start -= 0.75;
+ this._end += 1;
+ }
+
+ if (this.autoScale == true) {
+ this.setMinimumStep(minimumStep, containerHeight);
+ }
+
+ this.setFirst(customRange);
+ };
+
+ /**
+ * Automatically determine the scale that bests fits the provided minimum step
+ * @param {Number} [minimumStep] The minimum step size in milliseconds
+ */
+ DataStep.prototype.setMinimumStep = function(minimumStep, containerHeight) {
+ // round to floor
+ var size = this._end - this._start;
+ var safeSize = size * 1.2;
+ var minimumStepValue = minimumStep * (safeSize / containerHeight);
+ var orderOfMagnitude = Math.round(Math.log(safeSize)/Math.LN10);
+
+ var minorStepIdx = -1;
+ var magnitudefactor = Math.pow(10,orderOfMagnitude);
+
+ var start = 0;
+ if (orderOfMagnitude < 0) {
+ start = orderOfMagnitude;
+ }
+
+ var solutionFound = false;
+ for (var i = start; Math.abs(i) <= Math.abs(orderOfMagnitude); i++) {
+ magnitudefactor = Math.pow(10,i);
+ for (var j = 0; j < this.minorSteps.length; j++) {
+ var stepSize = magnitudefactor * this.minorSteps[j];
+ if (stepSize >= minimumStepValue) {
+ solutionFound = true;
+ minorStepIdx = j;
+ break;
+ }
+ }
+ if (solutionFound == true) {
+ break;
+ }
+ }
+ this.stepIndex = minorStepIdx;
+ this.scale = magnitudefactor;
+ this.step = magnitudefactor * this.minorSteps[minorStepIdx];
+ };
+
- this.setOptions(options);
- }
- Legend.prototype = new Component();
+ /**
+ * Round the current date to the first minor date value
+ * This must be executed once when the current date is set to start Date
+ */
+ DataStep.prototype.setFirst = function(customRange) {
+ if (customRange === undefined) {
+ customRange = {};
+ }
- Legend.prototype.clear = function() {
- this.groups = {};
- this.amountOfGroups = 0;
- }
+ var niceStart = customRange.min === undefined ? this._start - (this.scale * 2 * this.minorSteps[this.stepIndex]) : customRange.min;
+ var niceEnd = customRange.max === undefined ? this._end + (this.scale * this.minorSteps[this.stepIndex]) : customRange.max;
- Legend.prototype.addGroup = function(label, graphOptions) {
+ this.marginEnd = customRange.max === undefined ? this.roundToMinor(niceEnd) : customRange.max;
+ this.marginStart = customRange.min === undefined ? this.roundToMinor(niceStart) : customRange.min;
- if (!this.groups.hasOwnProperty(label)) {
- this.groups[label] = graphOptions;
+ // if we need to align the zero's we need to make sure that there is a zero to use.
+ if (this.alignZeros == true && (this.marginEnd - this.marginStart) % this.step != 0) {
+ this.marginEnd += this.marginEnd % this.step;
}
- this.amountOfGroups += 1;
- };
- Legend.prototype.updateGroup = function(label, graphOptions) {
- this.groups[label] = graphOptions;
- };
+ this.deadSpace = this.roundToMinor(niceEnd) - niceEnd + this.roundToMinor(niceStart) - niceStart;
+ this.marginRange = this.marginEnd - this.marginStart;
- Legend.prototype.removeGroup = function(label) {
- if (this.groups.hasOwnProperty(label)) {
- delete this.groups[label];
- this.amountOfGroups -= 1;
- }
- };
- Legend.prototype._create = function() {
- this.dom.frame = document.createElement('div');
- this.dom.frame.className = 'legend';
- this.dom.frame.style.position = "absolute";
- this.dom.frame.style.top = "10px";
- this.dom.frame.style.display = "block";
+ this.current = this.marginEnd;
+ };
- this.dom.textArea = document.createElement('div');
- this.dom.textArea.className = 'legendText';
- this.dom.textArea.style.position = "relative";
- this.dom.textArea.style.top = "0px";
+ DataStep.prototype.roundToMinor = function(value) {
+ var rounded = value - (value % (this.scale * this.minorSteps[this.stepIndex]));
+ if (value % (this.scale * this.minorSteps[this.stepIndex]) > 0.5 * (this.scale * this.minorSteps[this.stepIndex])) {
+ return rounded + (this.scale * this.minorSteps[this.stepIndex]);
+ }
+ else {
+ return rounded;
+ }
+ }
- this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg");
- this.svg.style.position = 'absolute';
- this.svg.style.top = 0 +'px';
- this.svg.style.width = this.options.iconSize + 5 + 'px';
- this.svg.style.height = '100%';
- this.dom.frame.appendChild(this.svg);
- this.dom.frame.appendChild(this.dom.textArea);
+ /**
+ * Check if the there is a next step
+ * @return {boolean} true if the current date has not passed the end date
+ */
+ DataStep.prototype.hasNext = function () {
+ return (this.current >= this.marginStart);
};
/**
- * Hide the component from the DOM
+ * Do the next step
*/
- Legend.prototype.hide = function() {
- // remove the frame containing the items
- if (this.dom.frame.parentNode) {
- this.dom.frame.parentNode.removeChild(this.dom.frame);
+ DataStep.prototype.next = function() {
+ var prev = this.current;
+ this.current -= this.step;
+
+ // safety mechanism: if current time is still unchanged, move to the end
+ if (this.current == prev) {
+ this.current = this._end;
}
};
/**
- * Show the component in the DOM (when not already visible).
- * @return {Boolean} changed
+ * Do the next step
*/
- Legend.prototype.show = function() {
- // show frame containing the items
- if (!this.dom.frame.parentNode) {
- this.body.dom.center.appendChild(this.dom.frame);
- }
+ DataStep.prototype.previous = function() {
+ this.current += this.step;
+ this.marginEnd += this.step;
+ this.marginRange = this.marginEnd - this.marginStart;
};
- Legend.prototype.setOptions = function(options) {
- var fields = ['enabled','orientation','icons','left','right'];
- util.selectiveDeepExtend(fields, this.options, options);
- };
- Legend.prototype.redraw = function() {
- var activeGroups = 0;
- 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)) {
- activeGroups++;
- }
- }
- }
- if (this.options[this.side].visible == false || this.amountOfGroups == 0 || this.options.enabled == false || activeGroups == 0) {
- this.hide();
- }
- else {
- this.show();
- if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'bottom-left') {
- this.dom.frame.style.left = '4px';
- this.dom.frame.style.textAlign = "left";
- this.dom.textArea.style.textAlign = "left";
- this.dom.textArea.style.left = (this.options.iconSize + 15) + 'px';
- this.dom.textArea.style.right = '';
- this.svg.style.left = 0 +'px';
- this.svg.style.right = '';
- }
- else {
- this.dom.frame.style.right = '4px';
- this.dom.frame.style.textAlign = "right";
- this.dom.textArea.style.textAlign = "right";
- this.dom.textArea.style.right = (this.options.iconSize + 15) + 'px';
- this.dom.textArea.style.left = '';
- this.svg.style.right = 0 +'px';
- this.svg.style.left = '';
- }
+ /**
+ * Get the current datetime
+ * @return {String} current The current date
+ */
+ DataStep.prototype.getCurrent = function(decimals) {
+ // prevent round-off errors when close to zero
+ var current = (Math.abs(this.current) < this.step / 2) ? 0 : this.current;
+ var toPrecision = '' + Number(current).toPrecision(5);
- if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'top-right') {
- this.dom.frame.style.top = 4 - Number(this.body.dom.center.style.top.replace("px","")) + 'px';
- this.dom.frame.style.bottom = '';
+ // If decimals is specified, then limit or extend the string as required
+ if(decimals !== undefined && !isNaN(Number(decimals))) {
+ // If string includes exponent, then we need to add it to the end
+ var exp = "";
+ var index = toPrecision.indexOf("e");
+ if(index != -1) {
+ // Get the exponent
+ exp = toPrecision.slice(index);
+ // Remove the exponent in case we need to zero-extend
+ toPrecision = toPrecision.slice(0, index);
}
- else {
- var scrollableHeight = this.body.domProps.center.height - this.body.domProps.centerContainer.height;
- this.dom.frame.style.bottom = 4 + scrollableHeight + Number(this.body.dom.center.style.top.replace("px","")) + 'px';
- this.dom.frame.style.top = '';
+ index = Math.max(toPrecision.indexOf(","), toPrecision.indexOf("."));
+ if(index === -1) {
+ // No decimal found - if we want decimals, then we need to add it
+ if(decimals !== 0) {
+ toPrecision += '.';
+ }
+ // Calculate how long the string should be
+ index = toPrecision.length + decimals;
}
-
- if (this.options.icons == false) {
- this.dom.frame.style.width = this.dom.textArea.offsetWidth + 10 + 'px';
- this.dom.textArea.style.right = '';
- this.dom.textArea.style.left = '';
- this.svg.style.width = '0px';
+ else if(decimals !== 0) {
+ // Calculate how long the string should be - accounting for the decimal place
+ index += decimals + 1;
+ }
+ if(index > toPrecision.length) {
+ // We need to add zeros!
+ for(var cnt = index - toPrecision.length; cnt > 0; cnt--) {
+ toPrecision += '0';
+ }
}
else {
- this.dom.frame.style.width = this.options.iconSize + 15 + this.dom.textArea.offsetWidth + 10 + 'px'
- this.drawLegendIcons();
+ // we need to remove characters
+ toPrecision = toPrecision.slice(0, index);
}
-
- var content = '';
- 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)) {
- content += this.groups[groupId].content + '
';
+ // Add the exponent if there is one
+ toPrecision += exp;
+ }
+ else {
+ if (toPrecision.indexOf(",") != -1 || toPrecision.indexOf(".") != -1) {
+ // If no decimal is specified, and there are decimal places, remove trailing zeros
+ for (var i = toPrecision.length - 1; i > 0; i--) {
+ if (toPrecision[i] == "0") {
+ toPrecision = toPrecision.slice(0, i);
+ }
+ else if (toPrecision[i] == "." || toPrecision[i] == ",") {
+ toPrecision = toPrecision.slice(0, i);
+ break;
+ }
+ else {
+ break;
}
}
}
- this.dom.textArea.innerHTML = content;
- this.dom.textArea.style.lineHeight = ((0.75 * this.options.iconSize) + this.options.iconSpacing) + 'px';
}
+
+ return toPrecision;
};
- Legend.prototype.drawLegendIcons = function() {
- if (this.dom.frame.parentNode) {
- DOMutil.prepareElements(this.svgElements);
- var padding = window.getComputedStyle(this.dom.frame).paddingTop;
- var iconOffset = Number(padding.replace('px',''));
- var x = iconOffset;
- var iconWidth = this.options.iconSize;
- var iconHeight = 0.75 * this.options.iconSize;
- var y = iconOffset + 0.5 * iconHeight + 3;
- this.svg.style.width = iconWidth + 5 + iconOffset + 'px';
- 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 + this.options.iconSpacing;
- }
- }
- }
+ /**
+ * Snap a date to a rounded value.
+ * The snap intervals are dependent on the current scale and step.
+ * @param {Date} date the date to be snapped.
+ * @return {Date} snappedDate
+ */
+ DataStep.prototype.snap = function(date) {
- DOMutil.cleanupElements(this.svgElements);
- }
};
- module.exports = Legend;
+ /**
+ * Check if the current value is a major value (for example when the step
+ * is DAY, a major value is each first day of the MONTH)
+ * @return {boolean} true if current date is major, else false.
+ */
+ DataStep.prototype.isMajor = function() {
+ return (this.current % (this.scale * this.majorSteps[this.stepIndex]) == 0);
+ };
+
+ module.exports = DataStep;
/***/ },
diff --git a/docs/graph2d.html b/docs/graph2d.html
index 05ab0579..bcab9602 100644
--- a/docs/graph2d.html
+++ b/docs/graph2d.html
@@ -452,6 +452,18 @@ The options colored in green can also be used as options for the groups. All opt