diff --git a/.eslintrc b/.eslintrc index 00d60a6e..1466a3db 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,6 +1,26 @@ { + "env": { + "browser": true, + "es6": true, + "node": true, + "mocha": true + }, + + "parser": "babel-eslint", + + "extends": "eslint:recommended", + "rules": { - "complexity": [2, 50], - "max-statements": [2, 100] + "complexity": [2, 55], + "max-statements": [2, 115], + "no-console": 0, + "no-empty": 0, + "no-extra-semi": 0, + "no-fallthrough": 0, + "no-inner-declarations": 0, + "no-mixed-spaces-and-tabs": 0, + "no-redeclare": 0, + "no-unreachable": 1, + "no-unused-vars": 0, } } diff --git a/.travis.yml b/.travis.yml index ce6f1da0..f12ed79f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: node_js node_js: "6" before_script: + - npm run lint - npm install -g gulp script: - gulp diff --git a/docs/network/edges.html b/docs/network/edges.html index 4125341c..58a775e1 100644 --- a/docs/network/edges.html +++ b/docs/network/edges.html @@ -935,7 +935,7 @@ var options: { String 'dynamic' Possible options: 'dynamic', 'continuous', 'discrete', 'diagonalCross', 'straightCross', 'horizontal', - 'vertical', 'curvedCW', 'curvedCCW', 'cubicBezier'. Take a look at our example 26 to see what these look like + 'vertical', 'curvedCW', 'curvedCCW', 'cubicBezier'. Take a look at this example to see what these look like and pick the one that you like best!

When using dynamic, the edges will have an invisible support node guiding the shape. This node is part of the diff --git a/lib/graph3d/Graph3d.js b/lib/graph3d/Graph3d.js index b0cbe8a0..e355c9db 100755 --- a/lib/graph3d/Graph3d.js +++ b/lib/graph3d/Graph3d.js @@ -12,13 +12,13 @@ var Settings = require('./Settings'); /// enumerate the available styles -Graph3d.STYLE = Settings.STYLE; +Graph3d.STYLE = Settings.STYLE; /** * Following label is used in the settings to describe values which should be * determined by the code while running, from the current data and graph style. - * + * * Using 'undefined' directly achieves the same thing, but this is more * descriptive by describing the intent. */ @@ -524,7 +524,7 @@ Graph3d.prototype._dataInitialize = function (rawData, style) { } } - + // set the scale dependent on the ranges. this._setScale(); }; @@ -699,7 +699,6 @@ Graph3d.prototype.create = function () { var onclick = function(event) {me._onClick(event);}; // TODO: these events are never cleaned up... can give a 'memory leakage' - util.addEventListener(this.frame.canvas, 'keydown', onkeydown); util.addEventListener(this.frame.canvas, 'mousedown', onmousedown); util.addEventListener(this.frame.canvas, 'touchstart', ontouchstart); util.addEventListener(this.frame.canvas, 'mousewheel', onmousewheel); @@ -902,7 +901,6 @@ Graph3d.prototype.setPointDrawingMethod = function() { default: throw new Error('Can not determine point drawing method ' + 'for graph style \'' + this.style + '\''); - break; } this._pointDrawingMethod = method; @@ -1338,7 +1336,7 @@ Graph3d.prototype._redrawAxis = function() { if (this.showYAxis) { xText = (armVector.y > 0) ? xRange.min : xRange.max; point3d = new Point3d(xText, y, zRange.min); - var msg = ' ' + this.yValueLabel(y) + ' '; + var msg = ' ' + this.yValueLabel(y) + ' '; this.drawAxisLabelY(ctx, point3d, msg, armAngle, textMargin); } diff --git a/lib/network/modules/LayoutEngine.js b/lib/network/modules/LayoutEngine.js index 2f4addfc..14a281e2 100644 --- a/lib/network/modules/LayoutEngine.js +++ b/lib/network/modules/LayoutEngine.js @@ -327,7 +327,6 @@ class LayoutEngine { // if the user defined some levels but not all, alert and run without hierarchical layout if (undefinedLevel === true && definedLevel === true) { throw new Error('To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes.'); - return; } else { // define levels if undefined by the users. Based on hubsize. diff --git a/lib/timeline/DateUtil.js b/lib/timeline/DateUtil.js index 5ff46f41..f361c7ee 100644 --- a/lib/timeline/DateUtil.js +++ b/lib/timeline/DateUtil.js @@ -500,7 +500,6 @@ exports.isHidden = function(time, hiddenDates) { if (time >= startDate && time < endDate) { // if the start is entering a hidden zone return {hidden: true, startDate: startDate, endDate: endDate}; - break; } } return {hidden: false, startDate: startDate, endDate: endDate}; diff --git a/lib/timeline/component/ItemSet.js b/lib/timeline/component/ItemSet.js index be95aa7d..972db387 100644 --- a/lib/timeline/component/ItemSet.js +++ b/lib/timeline/component/ItemSet.js @@ -1828,8 +1828,8 @@ ItemSet.prototype._onGroupDragEnd = function (event) { var switchGroup = dataset.get(newOrder[curPos]); var shouldBeGroup = dataset.get(origOrder[curPos]); me.options.groupOrderSwap(switchGroup, shouldBeGroup, dataset); - groupsData.update(switchGroup); - groupsData.update(shouldBeGroup); + dataset.update(switchGroup); + dataset.update(shouldBeGroup); var switchGroupId = newOrder[curPos]; newOrder[curPos] = origOrder[curPos]; diff --git a/lib/timeline/component/css/item.css b/lib/timeline/component/css/item.css index 67221d23..65923498 100644 --- a/lib/timeline/component/css/item.css +++ b/lib/timeline/component/css/item.css @@ -6,6 +6,7 @@ border-width: 1px; background-color: #D5DDF6; display: inline-block; + z-index: 1; /*overflow: hidden;*/ } @@ -103,6 +104,10 @@ white-space: nowrap; padding: 5px; border-radius: 1px; + transition: 0.4s; + -o-transition: 0.4s; + -moz-transition: 0.4s; + -webkit-transition: 0.4s; } .vis-item .vis-delete, .vis-item .vis-delete-rtl { diff --git a/lib/timeline/component/item/Item.js b/lib/timeline/component/item/Item.js index 5ddbd736..e41ef781 100644 --- a/lib/timeline/component/item/Item.js +++ b/lib/timeline/component/item/Item.js @@ -18,7 +18,7 @@ function Item (data, conversion, options) { this.data = data; this.dom = null; this.conversion = conversion || {}; - this.options = options || {}; + this.options = options || {}; this.selected = false; this.displayed = false; this.groupShowing = true; @@ -85,7 +85,7 @@ Item.prototype.setData = function(data) { remove: this.data.editable } } - else if(typeof options.editable === 'object') { + else if(typeof this.options.editable === 'object') { this.editable = {}; util.selectiveExtend(['updateTime', 'updateGroup', 'remove'], this.editable, data.editable); } diff --git a/misc/how_to_help.md b/misc/how_to_help.md index 63514fa4..9e08703b 100644 --- a/misc/how_to_help.md +++ b/misc/how_to_help.md @@ -12,7 +12,7 @@ A better way to ask questions on how to use vis.js is [stackoverflow](https://st ### Closing old issues -A new issue is often opened fast and then forgotten. Please help go trough [the old issues](//github.com/almende/vis/issues?q=is%3Aissue+is%3Aopen+sort%3Acreated-asc) (especially the [questions](//github.com/almende/vis/issues?q=is%3Aissue+is%3Aopen+sort%3Acreated-asc+label%3AQuestion)) and ask the creator of the issues if the problem still exists before closing the issue. The support team uses the **issue inactive** label to mark these issues. +A new issue is often opened fast and then forgotten. Please help go through [the old issues](//github.com/almende/vis/issues?q=is%3Aissue+is%3Aopen+sort%3Acreated-asc) (especially the [questions](//github.com/almende/vis/issues?q=is%3Aissue+is%3Aopen+sort%3Acreated-asc+label%3AQuestion)) and ask the creator of the issues if the problem still exists before closing the issue. The support team uses the **issue inactive** label to mark these issues. ### Improve the webpage diff --git a/package.json b/package.json index 8326d010..bed62546 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "scripts": { "test": "mocha", "build": "gulp", + "lint": "eslint lib", "watch": "gulp watch", "watch-dev": "gulp watch --bundle" }, @@ -45,8 +46,10 @@ }, "devDependencies": { "async": "^2.1.4", + "babel-eslint": "^7.1.1", "babelify": "^7.3.0", "clean-css": "^4.0.2", + "eslint": "^3.15.0", "gulp": "^3.9.1", "gulp-clean-css": "^2.3.2", "gulp-concat": "^2.6.1", diff --git a/test/PointItem.test.js b/test/PointItem.test.js new file mode 100644 index 00000000..1f88ea38 --- /dev/null +++ b/test/PointItem.test.js @@ -0,0 +1,65 @@ +var assert = require('assert'); +var vis = require('../dist/vis'); +var jsdom = require('mocha-jsdom'); +var moment = vis.moment; +var timeline = vis.timeline; +var PointItem = require("../lib/timeline/component/item/PointItem"); +var Range = timeline.Range; +var TestSupport = require('./TestSupport'); + +describe('Timeline PointItem', function () { + + jsdom(); + + it('should initialize with minimal data', function() { + var now = moment().toDate(); + var pointItem = new PointItem({start: now}, null, null); + assert.equal(pointItem.props.content.height, 0); + assert.equal(pointItem.data.start, now); + }); + + it('should have a default width of 0', function() { + var now = moment().toDate(); + var pointItem = new PointItem({start: now}, null, null); + assert.equal(pointItem.getWidthRight(), 0); + assert.equal(pointItem.getWidthLeft(), 0); + }); + + it('should error if there is missing data', function () { + assert.throws(function () { new PointItem({}, null, null)}, Error); + }); + + it('should be visible if the range is during', function() { + var now = moment(); + var range = new Range(TestSupport.buildSimpleTimelineRangeBody()); + range.start = now.clone().add(-1, 'second'); + range.end = range.start.clone().add(1, 'hour'); + var pointItem = new PointItem({start: now.toDate()}, null, null); + assert(pointItem.isVisible(range)); + }); + + it('should not be visible if the range is after', function() { + var now = moment(); + var range = new Range(TestSupport.buildSimpleTimelineRangeBody()); + range.start = now.clone().add(1, 'second'); + range.end = range.start.clone().add(1, 'hour'); + var pointItem = new PointItem({start: now.toDate()}, null, null); + assert(!pointItem.isVisible(range)); + }); + + it('should not be visible if the range is before', function() { + var now = moment(); + var range = new Range(TestSupport.buildSimpleTimelineRangeBody()); + range.end = now.clone().add(-1, 'second'); + range.start = range.end.clone().add(-1, 'hour'); + var pointItem = new PointItem({start: now.toDate()}, null, null); + assert(!pointItem.isVisible(range)); + }); + + it('should be visible for a "now" point with a default range', function() { + var range = new Range(TestSupport.buildSimpleTimelineRangeBody()); + var now = moment().toDate(); + var pointItem = new PointItem({start: now}, null, null); + assert(pointItem.isVisible(range)); + }); +}); \ No newline at end of file diff --git a/test/TestSupport.js b/test/TestSupport.js new file mode 100644 index 00000000..06d67852 --- /dev/null +++ b/test/TestSupport.js @@ -0,0 +1,22 @@ + +module.exports = { + buildSimpleTimelineRangeBody: function () { + var body = { + dom: { + center: { + clientWidth: 1000 + } + }, + domProps: this.props, + emitter: { + on: function () {}, + off: function () {}, + emit: function () {} + }, + hiddenDates: [], + util: {} + } + body.dom.rollingModeBtn = document.createElement('div') + return body + } +} diff --git a/test/TimelineRange.test.js b/test/TimelineRange.test.js index ba79142d..f73d84df 100644 --- a/test/TimelineRange.test.js +++ b/test/TimelineRange.test.js @@ -4,26 +4,7 @@ var jsdom = require('mocha-jsdom') var moment = vis.moment; var timeline = vis.timeline; var Range = timeline.Range; - -function buildSimpleBody() { - var body = { - dom: { - center: { - clientWidth: 1000 - } - }, - domProps: this.props, - emitter: { - on: function() {}, - off: function() {}, - emit: function() {} - }, - hiddenDates: [], - util: {} - }; - body.dom.rollingModeBtn = document.createElement('div'); - return body; -} +var TestSupport = require('./TestSupport'); describe('Timeline Range', function () { @@ -31,30 +12,30 @@ describe('Timeline Range', function () { it('should have start default before now', function () { var now = moment().hours(0).minutes(0).seconds(0).milliseconds(0).valueOf(); - var range = new Range(buildSimpleBody()); + var range = new Range(TestSupport.buildSimpleTimelineRangeBody()); assert(range.start < now, "Default start is before now"); }); it('should have end default after now', function () { var now = moment().hours(0).minutes(0).seconds(0).milliseconds(0).valueOf(); - var range = new Range(buildSimpleBody()); + var range = new Range(TestSupport.buildSimpleTimelineRangeBody()); assert(range.end > now, "Default end is after now"); }); it('should support custom start and end dates', function () { - var range = new Range(buildSimpleBody()); + var range = new Range(TestSupport.buildSimpleTimelineRangeBody()); range.setRange(new Date(2017, 0, 26, 13, 26, 3, 320), new Date(2017, 3, 11, 0, 23, 35, 0), false, false, null); assert.equal(range.start, new Date(2017, 0, 26, 13, 26, 3, 320).valueOf(), "start is as expected"); assert.equal(range.end, new Date(2017, 3, 11, 0, 23, 35, 0).valueOf(), "end is as expected"); }); it('should calculate milliseconds per pixel', function () { - var range = new Range(buildSimpleBody()); + var range = new Range(TestSupport.buildSimpleTimelineRangeBody()); assert(range.getMillisecondsPerPixel() > 0, "positive value for milliseconds per pixel"); }); it('should calculate 1 millisecond per pixel for simple range', function () { - var range = new Range(buildSimpleBody()); + var range = new Range(TestSupport.buildSimpleTimelineRangeBody()); range.setRange(new Date(2017, 0, 26, 13, 26, 3, 320), new Date(2017, 0, 26, 13, 26, 4, 320), false, false, null); assert.equal(range.getMillisecondsPerPixel(), 1, "one second over 1000 pixels"); });