New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Item visibility bug, some items get stuck on the left even if they are not in the visible range #1521

Open
kolin182 opened this Issue Dec 17, 2015 · 3 comments

Comments

Projects
None yet
5 participants
@kolin182
Copy link

kolin182 commented Dec 17, 2015

Hi, this issue is hard to reproduce but occurs from time to time..

There are some items which date is out of the visible range, but for some reason it keeps showing on the left of the timeline:

timeline.getVisibleItems()
["P963VN8", "PZP9N30", "PMUZAY5", "P080SGU", "PQ4T03D", "P9WNZ76", "P30PQAO", "PIML630", "PV789OZ", "PD4PTFR", "PJ8IMNJ", "PTAYQY8", "P2HITGH", "PGRX120", "PK4NQF6", "P4WB7B5", "P0Y49WV", "PYD9D77", "P62M42U", "POWZLJ1", "PSIYFT9", "PV5VMRZ", "P6Z1TCQ", "PTIYMM9"]

image

Some ideas of where to check? Trying to find where the items are removed and some way to fix it.. Maybe a function that remove from the DOM items that are not on the result of getVisibleItems?

Thanks in advance.

@josdejong

This comment has been minimized.

Copy link
Member

josdejong commented Dec 18, 2015

Hm, without being able to reproduce this issue we can't fix it.

@josdejong josdejong added the Timeline label Dec 18, 2015

@lhttjdr

This comment has been minimized.

Copy link

lhttjdr commented Jan 19, 2016

In my case, this bug only occurs when an item has not end field, such like BoxItem and PointItem.

Reproduction

I just modify a little of the example vis\examples\timeline\groups\groupsOrdering.html.

  • add the zoomMax option in options, for example,

    zoomMax: 1000 * 60 * 60 * 24 * 31 * 12 * 5
    

Without this setting, it will re-size the window to show all items.

  • add two invisible item, such like

    {id: 6, group: 2, content: 'item 6', start: new Date(2090, 3, 24), end: new Date(2099, 3, 27)},
    {id: 7, group: 2, content: 'item 7', start: new Date(2080, 3, 24)}
    

Because these two items are in distant future, they will be invisible in the initial view.
In this example, item7 stucks on left, however, item6 is in position. Now, I will explain the reason.

Analysis

It's a little bit long, you can skip it to read the fix section.
I use the single-file distribution version vis.js for debugging. So I do not know which file is the code in, but I will show their function names.

The following code is in function Timeline.prototype.setItems

this.itemsData = newDataSet;
this.itemSet && this.itemSet.setItems(newDataSet);
if (initialLoad) {
    if (this.options.start != undefined || this.options.end != undefined) {
        if (this.options.start == undefined || this.options.end == undefined) {
            var range = this.getItemRange();
        }
        var start = this.options.start != undefined ? this.options.start : range.min;
        var end = this.options.end != undefined ? this.options.end : range.max;

        this.setWindow(start, end, {
            animation: false
        });
    } else {
        this.fit({
            animation: false
        });
    }
}

The second line this.itemSet && this.itemSet.setItems(newDataSet); is the key point. From the code, I know that TimeSet.prototype.setItems() method can pick up the visible items. The following are some important code fragment.

  1. TimeSet.prototype.setItems()

    // add all new items
    ids = this.itemsData.getIds();
    this._onAdd(ids);
    
  2. TimeSet.prototype._onAdd()

    ItemSet.prototype._onAdd = ItemSet.prototype._onUpdate;
    
  3. TimeSet.prototype._onUpdate()

item = new constructor(itemData, me.conversion, me.options);
item.id = id; // TODO: not so nice setting id afterwards
me._addItem(item);
  1. TimeSet.prototype._addItem()
// add to group
var groupId = this._getGroupId(item.data);
var group = this.groups[groupId];
if (group) group.add(item);
  1. Group.prototype.add()

    if (this.visibleItems.indexOf(item) == -1) {
        var range = this.itemSet.body.range; // TODO: not nice accessing the range like this
        this._checkIfVisible(item, this.visibleItems, range);
    }
    
  2. Group.prototype._checkIfVisible()

    if (item.isVisible(range)) {
        if (!item.displayed) item.show();
        // reposition item horizontally
        item.repositionX();
        visibleItems.push(item);
    } else {
        if (item.displayed) item.hide();
    }
    

In the 5-th part, it uses _checkIfVisible to add visible items into visibleItems. In other word, it shows the visible items, and hides the invisible items.

Then, I notice that after setting the items, it calls Timeline.prototype.fit(). It's the bug!

  1. Timeline.prototype.fit()

    var range = this.getItemRange();
    this.range.setRange(range.min, range.max, animation);
    
  2. Timeline.prototype.getItemRange()

    util.forEach(_this.itemSet.items, (function(item) {
        item.show();
        .......
    }
    

It makes all items displayed to calculate the total range. So, the hidden items in previous step will be shown now. Without the repositionX(), they will stuck on left border.

In addition, why does range item not have this bug?
Because in function Group.prototype._updateVisibleItems, the range items will be hidden again.

if (this.checkRangedItems == true) {
    this.checkRangedItems = false;
    for (i = 0; i < orderedItems.byEnd.length; i++) {
        this._checkIfVisibleWithReference(orderedItems.byEnd[i], visibleItems,
        visibleItemsLookup, range);
    }
}

Fix

In the function Timeline.protoype.setItems(), move this line

this.itemSet && this.itemSet.setItems(newDataSet);

to the end of this function.
notice In the example, if you call timeline.fit() after setting items, it also raise this bug. So, I think it is better to add some restriction to the fit() function.

@josdejong josdejong closed this in 7cf090e Feb 1, 2016

@yoshimoto

This comment has been minimized.

Copy link

yoshimoto commented Feb 7, 2019

I have same problem.
I wrote small code to reproduce this issue.

<head>
  <script src="../libs/vis.min.js"></script>
  <link  href="../libs/vis-timeline-graph2d.min.css" rel="stylesheet" type="text/css" />
</head>

<div id="TL1"></div>
<div id="TL2"></div>
  
<script>
  var t1 = '2001-01-01T00:00:00.000Z';
  var t2 = '2001-01-01T00:00:10.000Z';
  var t3 = '2001-01-01T00:00:20.000Z';
  
  var items = new vis.DataSet();
  items.add({content: 'item 1', start: t1 });
  items.add({content: 'item 2', start: t2 });
  items.add({content: 'item 3', start: t3 });

  var options = {
  };
  var container = document.getElementById('TL1');
  var timeline = new vis.Timeline(container, items, options);
  timeline.setCurrentTime(t2);
  
  var options = {
      zoomMax: 10*1000,
  };
  var container = document.getElementById('TL2');
  var timeline = new vis.Timeline(container, items, options);
  timeline.setCurrentTime(t2);
</script>

This code will show two timelines, TL1(up) and TL2(bottom).

TL1 has no problem. Item 1, item 2, and item 3 are displayed in order from left to right.

TL2 has the problem. Item 3 gets stuck on the left.
Could you please scroll TL2? You will understand both Item 1 and Item 3 get stuck on the left.

@mojoaxel mojoaxel reopened this Feb 8, 2019

@mojoaxel mojoaxel added the Problem label Feb 8, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment