Search code examples
javascriptvis.jsvis.js-timeline

Visjs Dynamically Update a Timeline Item


I'm using visjs Timeline, and I'm trying to have an item expanding from current time for a duration of 2 days.

var items = new vis.DataSet([{
  id = 0,
  start = moment(new Date()),
  end = moment(new Date()).add(2, 'days')
}, /* And maybe more items */]);

When creating a new timeline:

var container = document.getElementById('container');
var timeline = new vis.Timeline(container, items, null);

Now I want to update one of my items (say, the first one) so that it always starts from the current time. I thought that currentTimeTick would be a good place to update:

timeline.on('currentTimeTick', function() {
  var itemData = timeline.itemSet.items[0].data;
  itemData.start = moment();   // Set the start to current time
  timeline.itemSet.items[0].setData(itemData);
}

When I debug in Chrome, I see that the start time in the items set is changed, but I'm not sure why the UI isn't updated to reflect that change (I expect the start of the item to match my current time).

I went through the source code, and it seems to me that setData should cause a redraw on the timeline, but I don't think it's happening. When I drag the timeline, it causes a redraw and the item is sized accordingly. Do I need to do something to force a redraw here?


Solution

  • Although calling timeline.redraw() is an option, it causes the whole timeline to be redrawn, which is expensive.

    The RangeItem has the method repositionX in its prototype, which apparently adjusts the horizontal position of the individual item, so what I did is to call this position after I set the data:

    timeline.itemSet.items[0].setData(itemData);
    timeline.itemSet.items[0].repositionX();
    

    EDIT: As @madebydavid suggested, instead of calling repositionX and setData directly, we can replace the two lines above with this single line:

    timeline.itemsData.update(itemData);
    

    Thanks @madebydavid