diff --git a/lib/timeline/Core.js b/lib/timeline/Core.js index 719c77cf..597fb753 100644 --- a/lib/timeline/Core.js +++ b/lib/timeline/Core.js @@ -137,7 +137,7 @@ Core.prototype._create = function (container) { // emitted via emitter this.hammer = new Hammer(this.dom.root); var pinchRecognizer = this.hammer.get('pinch').set({enable: true}); - hammerUtil.disablePreventDefaultVertically(pinchRecognizer); + pinchRecognizer && hammerUtil.disablePreventDefaultVertically(pinchRecognizer); this.hammer.get('pan').set({threshold:5, direction: Hammer.DIRECTION_HORIZONTAL}); this.listeners = {}; diff --git a/lib/timeline/Timeline.js b/lib/timeline/Timeline.js index 7310e623..84b35c91 100644 --- a/lib/timeline/Timeline.js +++ b/lib/timeline/Timeline.js @@ -448,6 +448,10 @@ Timeline.prototype.focus = function(id, options) { var verticalAnimationFrame = function(ease, willDraw, done) { var verticalScroll = getItemVerticalScroll(me, item); + if (verticalScroll === false) { + return; // We don't need to scroll, so do nothing + } + if(!initialVerticalScroll) { initialVerticalScroll = verticalScroll; } @@ -560,6 +564,11 @@ function getEnd(item) { * @return {{shouldScroll: bool, scrollOffset: number, itemTop: number}} */ function getItemVerticalScroll(timeline, item) { + if (!item.parent) { + // The item no longer exists, so ignore this focus. + return false; + } + var leftHeight = timeline.props.leftContainer.height; var contentHeight = timeline.props.left.height; diff --git a/test/Timeline.test.js b/test/Timeline.test.js new file mode 100644 index 00000000..355e3ffb --- /dev/null +++ b/test/Timeline.test.js @@ -0,0 +1,44 @@ +var DataSet = require('../lib/DataSet'); +var Timeline = require('../lib/timeline/Timeline'); + +describe('Timeline', function () { + before(function () { + this.jsdom = require('jsdom-global')({ + pretendToBeVisual: true + }); + global['Element'] = window.Element; + global['requestAnimationFrame'] = function(cb) { + cb(); + }; + }); + + after(function () { + this.jsdom(); + }); + + it('should not throw when updating data in close succession', function (done) { + var timeline = new Timeline(document.createElement('div'), []); + + var events = [ + {start: new Date(), id: 1}, + {start: new Date(), id: 2} + ]; + + timeline + .setItems(new DataSet(events)); + + setTimeout(function() { + timeline + .setItems(new DataSet([ + {start: new Date(), id: 3}, + {start: new Date(), id: 4}, + {start: new Date(), id: 5} + ])); + + done(); + }, 5); + + timeline + .setSelection([events[0].id], {animation: false}); + }); +});