Search code examples
javascripttimelinevis.jsvis.js-timelinevis-timeline

How to include custom data into vis.js timeline item


I have been using vis.js timeline to keep items in a time order.

I use the following to add timeline items :

timeline_items.add({
    id              : entity_id + uuidv4(),
    group           : "timeline_video_group_id",
    start           : start_date,
    end             : end_date,
    content         : "<img src='" + element_src_link + "'></img>",
    className       : 'imagecontainer'
});

However, I cannot add any custom data into this add function.

How may I add custom data, so it may hold information such as entity-uuid=xxxx inside the div below ?

<div class="vis-item vis-range imagecontainer vis-editable" style="transform...">
  <div class="vis-item-overflow">
    <div class="vis-item-content" style="transform: translateX(0px);">
      <img src="image_src">
    </div>
    <div class="vis-item-visible-frame">
    </div>
  </div>
</div>

Solution

  • You can update the content to the full HTML you would like, including an image and text, then store this in the DataSet. The vis.js example named 'Custom Styling' here uses this approach.

    content: '<div>Mail from boss</div><img src="../resources/img/mail-icon.png" style="width:32px; height:32px;">',
    

    Alternatively you could add custom data to the items in the DataSet, then use the template feature described in the documentation here to construct the HTML. This is the approach I would use.

    An example of a template is incorporated into the post below and also at https://jsfiddle.net/xm95u40f/. The example adds a property named imageColor to each item in the DataSet, this is used in combination with the text from the content to display the item. You could store and use your entity-uuid value in a similar way.

    // DOM element where the Timeline will be attached
    var container = document.getElementById("visualization");
    
    // Create a DataSet (allows two way data-binding)
    var items = new vis.DataSet();
    
    items.add([
      { id: 1, content: "item 1", start: "2021-12-21", end: "2021-12-23", imageColor: "0000FF" },
      { id: 2, content: "item 2", start: "2021-12-14", end: "2021-12-17", imageColor: "FFFFFF" },
      { id: 3, content: "item 3", start: "2021-12-18", end: "2021-12-20", imageColor: "0000FF" },
      { id: 4, content: "item 4", start: "2021-12-16", end: "2021-12-21", imageColor: "FFFFFF" },
      { id: 5, content: "item 5", start: "2021-12-25", end: "2021-12-27", imageColor: "000000" },
      { id: 6, content: "item 6", start: "2021-12-27", end: "2021-12-28", imageColor: "008000" },
    ]);
    
    // Configuration for the Timeline
    var options = {
      // Define a template function which constructions the HTML for each item
      template: function (item, element, data) {
        var html = "<img class='timeline-image' src='https://via.placeholder.com/40/" + item.imageColor + "'><div>" + item.content + "</div>"
        return html;
      },
      // Using a template requires any attributes to be whitelisted to prevent XSS
      // More details at https://github.com/visjs/vis-timeline/pull/1010
      xss: {
        disabled: false,
        filterOptions: {
          whiteList: { img: ['src', 'class'], div: 'class' }
        },
      },
    };
    
    // Create a Timeline
    var timeline = new vis.Timeline(container, items, options);
    body,
    html {
      font-family: sans-serif;
    }
    
    /* 
    Timeline image is defined with a fixed height and width.
    When the timeline loads it determines the size of items
    then uses this to place them, as the images won't be 
    loaded at this point the size must be set to ensure the 
    spacing is correct
    */
    .timeline-image {
      height: 40px;
      width: 40px
    }
    <script src="https://visjs.github.io/vis-timeline/standalone/umd/vis-timeline-graph2d.min.js"></script>
    <link href="https://visjs.github.io/vis-timeline/styles/vis-timeline-graph2d.min.css" rel="stylesheet"/>
    
    <div id="visualization"></div>